Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
/**
 * 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);
}
Ejemplo n.º 3
0
/**
 * 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);
}
Ejemplo n.º 5
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));
}
Ejemplo n.º 6
0
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__);
}
Ejemplo n.º 7
0
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);
    }
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
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);
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
/*
 * 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);
}