int ccn_buf_match_dtag(struct ccn_buf_decoder *d, enum ccn_dtag dtag) { return (d->decoder.state >= 0 && CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_DTAG && d->decoder.numval == dtag); }
/** * Parses a ccnb-encoded element expected to contain a UDATA string. * @param d is the decoder * @param dtag is the expected dtag value * @param store - on success, the string value is appended to store, * with null termination. * @returns the offset into the store buffer of the copied value, or -1 for error. * If a parse error occurs, d->decoder.state is set to a negative value. * If the element is not present, -1 is returned but no parse error * is indicated. */ int ccn_parse_tagged_string(struct ccn_buf_decoder *d, enum ccn_dtag dtag, struct ccn_charbuf *store) { const unsigned char *p = NULL; size_t size = 0; int res; if (ccn_buf_match_dtag(d, dtag)) { ccn_buf_advance(d); if (d->decoder.state >= 0 && CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) { res = store->length; p = d->buf + d->decoder.index; size = d->decoder.numval; ccn_buf_advance(d); } ccn_buf_check_close(d); if (d->decoder.state >= 0) { // XXX - should check for valid utf-8 data. res = store->length; if (size > 0) ccn_charbuf_append(store, p, size); ccn_charbuf_append_value(store, 0, 1); return(res); } } return(-1); }
/** * Parse a potentially large non-negative integer. * * @returns 0 for success, and the value is place in *result; for an error * a negative value is returned and *result is unchanged. */ int ccn_parse_uintmax(struct ccn_buf_decoder *d, uintmax_t *result) { const unsigned char *p; int i; int n; uintmax_t val; uintmax_t newval; unsigned char c; if (d->decoder.state < 0) return(d->decoder.state); if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) { p = d->buf + d->decoder.index; n = d->decoder.numval; if (n < 1) return(d->decoder.state = -__LINE__); val = 0; for (i = 0; i < n; i++) { c = p[i]; if ('0' <= c && c <= '9') { newval = val * 10 + (c - '0'); if (newval < val) return(d->decoder.state = -__LINE__); val = newval; } else return(d->decoder.state = -__LINE__); } ccn_buf_advance(d); *result = val; return(0); } return(d->decoder.state = -__LINE__); }
int ccn_ref_tagged_string(enum ccn_dtag dtag, const unsigned char *buf, size_t start, size_t stop, const unsigned char **presult, size_t *psize) { struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d; const unsigned char *result = NULL; size_t size = 0; if (stop < start) return(-1); d = ccn_buf_decoder_start(&decoder, buf + start, stop - start); if (ccn_buf_match_dtag(d, dtag)) { ccn_buf_advance(d); if (d->decoder.state >= 0 && CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) { result = d->buf + d->decoder.index; size = d->decoder.numval; ccn_buf_advance(d); } ccn_buf_check_close(d); } else return(-1); if (d->decoder.index != d->size || !CCN_FINAL_DSTATE(d->decoder.state)) return (CCN_DSTATE_ERR_CODING); if (presult) *presult = result; if (psize) *psize = size; return(0); }
int ccn_buf_match_attr(struct ccn_buf_decoder *d, const char *s) { size_t len = strlen(s); return (d->decoder.state >= 0 && CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_ATTR && d->decoder.numval == len && 0 == memcmp(d->buf + d->decoder.index, s, len)); }
int ccn_parse_timestamp(struct ccn_buf_decoder *d) { const unsigned char dlm[] = "--T::.Z"; const unsigned char *p; int i; int k; int n; if (d->decoder.state < 0) return(d->decoder.state); if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_BLOB) { /* New-style binary timestamp, 12-bit fraction */ n = d->decoder.numval; if (n < 3 || n > 7) return(d->decoder.state = -__LINE__); ccn_buf_advance(d); return(0); } if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) { /* This is for some temporary back-compatibility */ p = d->buf + d->decoder.index; n = d->decoder.numval; if (n < 8 || n > 40) return(d->decoder.state = -__LINE__); if (p[n - 1] != 'Z') return(d->decoder.state = -__LINE__); for (i = 0, k = 0; i < n && '0' <= p[i] && p[i] <= '9';) { i++; if (i < n && p[i] == dlm[k]) { if (dlm[k++] == 0) return(d->decoder.state = -__LINE__); i++; } } if (k < 5) return(d->decoder.state = -__LINE__); if (!(i == n || i == n - 1)) return(d->decoder.state = -__LINE__); ccn_buf_advance(d); return(0); } return(d->decoder.state = -__LINE__); }
void ccn_buf_check_close(struct ccn_buf_decoder *d) { if (d->decoder.state >= 0) { if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) != CCN_NO_TOKEN) d->decoder.state = CCN_DSTATE_ERR_NEST; else ccn_buf_advance(d); } }
int ccn_parse_required_tagged_UDATA(struct ccn_buf_decoder *d, enum ccn_dtag dtag) { int res = -1; if (ccn_buf_match_dtag(d, dtag)) { res = d->decoder.element_index; ccn_buf_advance(d); if (d->decoder.state >= 0 && CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) ccn_buf_advance(d); else d->decoder.state = -__LINE__; ccn_buf_check_close(d); } else d->decoder.state = -__LINE__; if (d->decoder.state < 0) return (-1); return(res); }
int ccn_buf_advance_past_element(struct ccn_buf_decoder *d) { enum ccn_tt tt; int nest; if (d->decoder.state < 0) return(d->decoder.state); tt = CCN_GET_TT_FROM_DSTATE(d->decoder.state); if (tt == CCN_DTAG || tt == CCN_TAG) { nest = d->decoder.nest; ccn_buf_advance(d); while (d->decoder.state >= 0 && d->decoder.nest >= nest) ccn_buf_advance(d); /* The nest decrements before the closer is consumed */ ccn_buf_check_close(d); } else return(-1); if (d->decoder.state < 0) return(d->decoder.state); return (0); }
int ccn_buf_match_some_blob(struct ccn_buf_decoder *d) { return(d->decoder.state >= 0 && CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_BLOB); }
int ccn_buf_match_some_dtag(struct ccn_buf_decoder *d) { return(d->decoder.state >= 0 && CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_DTAG); }
/* * Dissector that returns: * * The amount of data in the protocol's PDU, if it was able to * dissect all the data; * * 0, if the tvbuff doesn't contain a PDU for that protocol; * * The negative of the amount of additional data needed, if * we need more data (e.g., from subsequent TCP segments) to * dissect the entire PDU. */ static int dissect_ccn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint tvb_size = 0; proto_tree *ccn_tree; proto_item *ti = NULL; const unsigned char *ccnb; struct ccn_skeleton_decoder skel_decoder; struct ccn_skeleton_decoder *sd; struct ccn_charbuf *c; int packet_type = 0; int packet_type_length = 0; /* a couple of basic checks to rule out packets that are definitely not ours */ tvb_size = tvb_length(tvb); if (tvb_size < CCN_MIN_PACKET_SIZE || tvb_get_guint8(tvb, 0) == 0) return (0); sd = &skel_decoder; memset(sd, 0, sizeof(*sd)); sd->state |= CCN_DSTATE_PAUSE; ccnb = ep_tvb_memdup(tvb, 0, tvb_size); ccn_skeleton_decode(sd, ccnb, tvb_size); if (sd->state < 0) return (0); if (CCN_GET_TT_FROM_DSTATE(sd->state) == CCN_DTAG) { packet_type = sd->numval; packet_type_length = sd->index; } else { return (0); } memset(sd, 0, sizeof(*sd)); ccn_skeleton_decode(sd, ccnb, tvb_size); if (!CCN_FINAL_DSTATE(sd->state)) { pinfo->desegment_offset = 0; pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; return (-1); /* what should this be? */ } /* Make it visible that we're taking this packet */ if (check_col(pinfo->cinfo, COL_PROTOCOL)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "CCN"); } /* Clear out stuff in the info column */ if (check_col(pinfo->cinfo, COL_INFO)) { col_clear(pinfo->cinfo, COL_INFO); } c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, tvb_size, 1); /* Add the packet type and CCN URI to the info column */ if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type, VALS(ccn_dtag_dict.dict), "Unknown (0x%02x")); col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, ccn_charbuf_as_string(c)); } if (tree == NULL) { ccn_charbuf_destroy(&c); return (sd->index); } ti = proto_tree_add_protocol_format(tree, proto_ccn, tvb, 0, -1, "Content-centric Networking Protocol, %s, %s", val_to_str(packet_type, VALS(ccn_dtag_dict.dict), "Unknown (0x%02x"), ccn_charbuf_as_string(c)); ccn_tree = proto_item_add_subtree(ti, ett_ccn); ccn_charbuf_destroy(&c); ti = proto_tree_add_uint(ccn_tree, hf_ccn_type, tvb, 0, packet_type_length, packet_type); switch (packet_type) { case CCN_DTAG_ContentObject: if (0 > dissect_ccn_contentobject(ccnb, sd->index, tvb, pinfo, ccn_tree)) return (0); break; case CCN_DTAG_Interest: if (0 > dissect_ccn_interest(ccnb, sd->index, tvb, pinfo, ccn_tree)) return (0); break; } return (sd->index); }