예제 #1
0
int ccnb_append_dhcp_content(struct ccn_charbuf *c, int count, const struct ccn_dhcp_entry *head)
{
    int res;
    int i;
    const struct ccn_dhcp_entry *de = head;

    res = ccnb_element_begin(c, CCN_DTAG_Entry);
    res |= ccnb_tagged_putf(c, CCN_DTAG_Count, "%d", count);

    for (i = 0; i < count; i ++) {
        if (de == NULL)
        {
            fprintf(stderr, "Error: number of ccn_dhcp_entry does not match\n");
            break;
        }

        if (de->name_prefix != NULL && de->name_prefix->length > 0)
            res |= ccn_charbuf_append(c, de->name_prefix->buf, de->name_prefix->length);

        if (de->address != NULL)
            res |= ccnb_tagged_putf(c, CCN_DTAG_Host, "%s", de->address);
        if (de->port != NULL)
            res |= ccnb_tagged_putf(c, CCN_DTAG_Port, "%s", de->port);

        de = de->next;
    }

    res |= ccnb_element_end(c);
    return res;
}
예제 #2
0
파일: ccn_reg_mgmt.c 프로젝트: Emat12/ccnx
int
ccnb_append_forwarding_entry(struct ccn_charbuf *c,
                             const struct ccn_forwarding_entry *fe)
{
    int res;
    res = ccnb_element_begin(c, CCN_DTAG_ForwardingEntry);
    if (fe->action != NULL)
        res |= ccnb_tagged_putf(c, CCN_DTAG_Action, "%s",
                                   fe->action);
    if (fe->name_prefix != NULL && fe->name_prefix->length > 0)
        res |= ccn_charbuf_append(c, fe->name_prefix->buf,
                                     fe->name_prefix->length);
    if (fe->ccnd_id_size != 0)
        res |= ccnb_append_tagged_blob(c, CCN_DTAG_PublisherPublicKeyDigest,
                                          fe->ccnd_id, fe->ccnd_id_size);
    if (fe->faceid != ~0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_FaceID, "%u",
                                   fe->faceid);
    if (fe->flags >= 0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_ForwardingFlags, "%d",
                                   fe->flags);
    if (fe->lifetime >= 0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_FreshnessSeconds, "%d",
                                   fe->lifetime);
    res |= ccnb_element_end(c);
    return(res);
}
예제 #3
0
파일: ccnrm.c 프로젝트: GabrielLiz/ccnx
/***********
<Interest>
  <Name/>
  <AnswerOriginKind>19</AnswerOriginKind>
  <Scope>0</Scope>
</Interest>
**********/
struct ccn_charbuf *
local_scope_rm_template(void)
{
    struct ccn_charbuf *templ = ccn_charbuf_create();
    ccnb_element_begin(templ, CCN_DTAG_Interest);
    ccnb_element_begin(templ, CCN_DTAG_Name);
    ccnb_element_end(templ); /* </Name> */
    ccnb_tagged_putf(templ, CCN_DTAG_AnswerOriginKind, "%2d",
                     (CCN_AOK_EXPIRE | CCN_AOK_DEFAULT));
    ccnb_tagged_putf(templ, CCN_DTAG_Scope, "0");
    ccnb_element_end(templ); /* </Interest> */
    return(templ);
}
예제 #4
0
/***********************************
 * Append a StatusResponse
 * 
 *  @param buf is the buffer to append to.
 *  @param errcode is a 3-digit error code.
 *            It should be documented in StatusResponse.txt.
 *  @param errtext is human-readable text (may be NULL).
 *  @returns 0 for success or -1 for error.
 */
int
ccn_encode_StatusResponse(struct ccn_charbuf *buf,
                          int errcode, const char *errtext)
{
    int res = 0;
    if (errcode < 100 || errcode > 999)
        return(-1);
    res |= ccn_charbuf_append_tt(buf, CCN_DTAG_StatusResponse, CCN_DTAG);
    res |= ccnb_tagged_putf(buf, CCN_DTAG_StatusCode, "%d", errcode);
    if (errtext != NULL && errtext[0] != 0)
        res |= ccnb_tagged_putf(buf, CCN_DTAG_StatusText, "%s", errtext);
    res |= ccn_charbuf_append_closer(buf);
    return(res);
}
예제 #5
0
static int
process_int_attribute(struct ccn_charbuf *interest, enum ccn_dtag tag,
		PyObject *py_obj_Interest, const char *attr_name)
{
	PyObject *py_attr;
	int val, r;

	r = is_attr_set(py_obj_Interest, attr_name, &py_attr);
	if (r <= 0)
		return r;

	val = _pyccn_Int_AsLong(py_attr);
	Py_DECREF(py_attr);
	if (PyErr_Occurred())
		return -1;

#if 0
	r = ccn_charbuf_append_tt(interest, tag, CCN_DTAG);
	JUMP_IF_NEG_MEM(r, error);

	r = ccnb_append_number(interest, val);
	JUMP_IF_NEG_MEM(r, error);

	r = ccn_charbuf_append_closer(interest); /* </Tag> */
	JUMP_IF_NEG_MEM(r, error);
#endif

	r = ccnb_tagged_putf(interest, tag, "%d", val);
	JUMP_IF_NEG_MEM(r, error);

	return 1;
error:
	return -1;
}
예제 #6
0
파일: ccndc.c 프로젝트: IthacaDream/ccnx
struct ccndc_data *
ccndc_initialize_data(void) {
    struct ccndc_data *self;
    const char *msg = "Unable to initialize ccndc";
    int res;
    
    self = calloc(1, sizeof(*self));
    if (self == NULL) {
        ON_ERROR_EXIT (-1, msg);
    }
    
    self->ccn_handle = ccn_create();
    ON_ERROR_EXIT(ccn_connect(self->ccn_handle, NULL), "Unable to connect to local ccnd");
    ON_ERROR_EXIT(ccndc_get_ccnd_id(self), "Unable to obtain ID of local ccnd");
    
    /* Set up an Interest template to indicate scope 1 (Local) */
    self->local_scope_template = ccn_charbuf_create();
    res = ccnb_element_begin(self->local_scope_template, CCN_DTAG_Interest);
    res |= ccnb_element_begin(self->local_scope_template, CCN_DTAG_Name);
    res |= ccnb_element_end(self->local_scope_template);	/* </Name> */
    res |= ccnb_tagged_putf(self->local_scope_template, CCN_DTAG_Scope, "1");
    res |= ccnb_element_end(self->local_scope_template);	/* </Interest> */
    ON_ERROR_EXIT(res, msg);
    
    /* Create a null name */
    self->no_name = ccn_charbuf_create();
    ON_ERROR_EXIT(ccn_name_init(self->no_name), msg);
    
    self->lifetime = (~0U) >> 1;
    
    return self;
}
예제 #7
0
/*
 * Append AnswerOriginKind element to partially constructed Interest,
 * requesting to not generate new content.
 */
static void
answer_passive(struct ccn_charbuf *templ, int allow_stale)
{
    int aok = CCN_AOK_CS;
    if (allow_stale)
        aok |= CCN_AOK_STALE;
    ccnb_tagged_putf(templ, CCN_DTAG_AnswerOriginKind, "%d", aok);
}
예제 #8
0
파일: sync_api.c 프로젝트: IthacaDream/ccnx
/*
 * utility, may need to be exported, to append the encoding of a
 * slice to a charbuf
 */
static int
append_slice(struct ccn_charbuf *c, struct ccns_slice *s) {
    int res = 0;
    int i;

    res |= ccnb_element_begin(c, CCN_DTAG_SyncConfigSlice);
    res |= ccnb_tagged_putf(c, CCN_DTAG_SyncVersion, "%u", SLICE_VERSION);
    res |= ccn_charbuf_append_charbuf(c, s->topo);
    res |= ccn_charbuf_append_charbuf(c, s->prefix);
    res |= ccnb_element_begin(c, CCN_DTAG_SyncConfigSliceList);
    for (i = 0; i < s->nclauses ; i++) {
        res |= ccnb_tagged_putf(c, CCN_DTAG_SyncConfigSliceOp, "%u", 0);
        res |= ccn_charbuf_append_charbuf(c, s->clauses[i]);
    }
    res |= ccnb_element_end(c);
    res |= ccnb_element_end(c);
    return (res);
}
예제 #9
0
int 
get_content_by_content_name(char *content_name, unsigned char **content_data,
							char *orig_router)
{
	
	int ret=-1;
	struct ccn_charbuf *name = NULL;
	struct ccn_charbuf *templ = NULL;
	struct ccn_charbuf *resultbuf = NULL;
	struct ccn_parsed_ContentObject pcobuf = { 0 };
	int res;
	int allow_stale = 1;
	int content_only = 1;
	int scope = -1;
	const unsigned char *ptr,*ptr_in; 
	size_t length,length_in;
	int resolve_version = CCN_V_HIGHEST;
	int timeout_ms = 3000;
	const unsigned lifetime_default = CCN_INTEREST_LIFETIME_SEC << 12;
	unsigned lifetime_l12 = lifetime_default;
	int get_flags = 0;

	name = ccn_charbuf_create();
	res = ccn_name_from_uri(name,content_name);
	if (res < 0) {
		fprintf(stderr, "Bad ccn URI: %s\n", content_name);
		ccn_charbuf_destroy(&name);
		return ret;
	}

	if (allow_stale || lifetime_l12 != lifetime_default || scope != -1) {
		templ = ccn_charbuf_create();
		ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
		ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
		ccn_charbuf_append_closer(templ); /* </Name> */
		if (allow_stale) {
			ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
			ccnb_append_number(templ,
					CCN_AOK_DEFAULT | CCN_AOK_STALE);
			ccn_charbuf_append_closer(templ); /* </AnswerOriginKind> */
		}
		if (scope != -1) {
			ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", scope);
		}
		if (lifetime_l12 != lifetime_default) {
			/*
			 * Choose the interest lifetime so there are at least 3
			 * expressions (in the unsatisfied case).
			 */
			unsigned char buf[3] = { 0 };
			int i;
			for (i = sizeof(buf) - 1; i >= 0; i--, lifetime_l12 >>= 8)
				buf[i] = lifetime_l12 & 0xff;
			ccnb_append_tagged_blob(templ, CCN_DTAG_InterestLifetime, buf, 
					sizeof(buf));
		}
예제 #10
0
int
ccnb_append_strategy_selection(struct ccn_charbuf *c,
                               const struct ccn_strategy_selection *ss)
{
    int ch;
    int i;
    int len;
    int res;
    
    res = ccnb_element_begin(c, CCN_DTAG_StrategySelection);
    if (ss->action != NULL)
        res |= ccnb_tagged_putf(c, CCN_DTAG_Action, "%s",
                                   ss->action);
    if (ss->name_prefix != NULL && ss->name_prefix->length > 0)
        res |= ccn_charbuf_append(c, ss->name_prefix->buf,
                                     ss->name_prefix->length);
    if (ss->ccnd_id_size != 0)
        res |= ccnb_append_tagged_blob(c, CCN_DTAG_PublisherPublicKeyDigest,
                                          ss->ccnd_id, ss->ccnd_id_size);
    if (ss->strategyid != NULL) {
        len = strlen(ss->strategyid);
        for (i = 0; i < len; i++) {
            ch = ss->strategyid[i];
            if (!(('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z') ||
                  ('0' <= ch && ch <= '9') || (ch == '_')))
                res |= -1;
        }
        if (len > 0) {
            res |= ccnb_tagged_putf(c, CCN_DTAG_StrategyID, "%.15s",
                                       ss->strategyid);
            if (len >= STRATEGY_ID_MAX_SIZE)
                res |= -1;
        }
    }
    if (ss->parameters != NULL)
        res |= ccnb_tagged_putf(c, CCN_DTAG_StrategyParameters, "%s",
                                   ss->parameters);
    if (ss->lifetime >= 0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_FreshnessSeconds, "%d",
                                   ss->lifetime);
    res |= ccnb_element_end(c);
    return(res);
}
예제 #11
0
/*
 * initialize local data
 */
void init_data(struct ccn_charbuf *local_scope_template,
        struct ccn_charbuf *no_name)
{
    ccn_charbuf_append_tt(local_scope_template, CCN_DTAG_Interest, CCN_DTAG);
    ccn_charbuf_append_tt(local_scope_template, CCN_DTAG_Name, CCN_DTAG);
    ccn_charbuf_append_closer(local_scope_template);    /* </Name> */
    ccnb_tagged_putf(local_scope_template, CCN_DTAG_Scope, "1");
    ccn_charbuf_append_closer(local_scope_template);    /* </Interest> */

    ccn_name_init(no_name);
}
예제 #12
0
파일: sync_api.c 프로젝트: IthacaDream/ccnx
struct ccn_charbuf *
make_scope1_template(void) {
    struct ccn_charbuf *templ = NULL;
    templ = ccn_charbuf_create_n(16);
    ccnb_element_begin(templ, CCN_DTAG_Interest);
    ccnb_element_begin(templ, CCN_DTAG_Name);
    ccnb_element_end(templ); /* </Name> */
    ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%u", 1);
    ccnb_element_end(templ); /* </Interest> */
    return(templ);
}
예제 #13
0
파일: CcnClient.c 프로젝트: ltr120/NDNFD
struct ccn_charbuf* CcnH_localScopeTempl(void) {
	if (CcnH_localScopeTempl_inst == NULL) {
		CcnH_localScopeTempl_inst = ccn_charbuf_create();
		ccn_charbuf_append_tt(CcnH_localScopeTempl_inst, CCN_DTAG_Interest, CCN_DTAG);
		ccn_charbuf_append_tt(CcnH_localScopeTempl_inst, CCN_DTAG_Name, CCN_DTAG);
		ccn_charbuf_append_closer(CcnH_localScopeTempl_inst);
		ccnb_tagged_putf(CcnH_localScopeTempl_inst, CCN_DTAG_Scope, "1");
		ccn_charbuf_append_closer(CcnH_localScopeTempl_inst);
	}
	return CcnH_localScopeTempl_inst;
}
예제 #14
0
파일: ccnseqwriter.c 프로젝트: remap/ws-ndn
/*
 * make_template: construct an interest template containing the specified scope
 *     An unlimited scope is passed in as 3, and the omission of the scope
 *     field from the template indicates this.
 */
struct ccn_charbuf *
make_template(int scope)
{
    struct ccn_charbuf *templ = NULL;
    templ = ccn_charbuf_create();
    ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
    ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
    ccn_charbuf_append_closer(templ); /* </Name> */
    if (0 <= scope && scope <= 2)
        ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", scope);
    ccn_charbuf_append_closer(templ); /* </Interest> */
    return(templ);
}
예제 #15
0
/*
 * make_template: construct an interest template containing the specified scope
 *     An unlimited scope is passed in as 3, and the omission of the scope
 *     field from the template indicates this.
 */
struct ccn_charbuf *
make_template(int scope)
{
    struct ccn_charbuf *templ = NULL;
    templ = ccn_charbuf_create();
    ccnb_element_begin(templ, CCN_DTAG_Interest);
    ccnb_element_begin(templ, CCN_DTAG_Name);
    ccnb_element_end(templ); /* </Name> */
    if (0 <= scope && scope <= 2)
        ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", scope);
    ccnb_element_end(templ); /* </Interest> */
    return(templ);
}
예제 #16
0
파일: CcnClient.c 프로젝트: ltr120/NDNFD
void CcnCC_sendContent(CcnCC self, struct ccn_charbuf* name, TimeSpan expires, void* data, size_t size) {
	struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
	if (expires >= 0) {
		sp.template_ccnb = ccn_charbuf_create();
		ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
		ccnb_tagged_putf(sp.template_ccnb, CCN_DTAG_FreshnessSeconds, "%ld", expires / 1000);
		sp.sp_flags |= CCN_SP_TEMPL_FRESHNESS;
		ccn_charbuf_append_closer(sp.template_ccnb);
	}
	struct ccn_charbuf* content = ccn_charbuf_create();
	if (0 == ccn_sign_content(self->ccnh, content, name, &sp, data, size)) {
		ccn_put(self->ccnh, content->buf, content->length);
	}
	ccn_charbuf_destroy(&sp.template_ccnb);
	ccn_charbuf_destroy(&content);
}
/**
* Creates a template for ccn interest fetch
*
* @param allow_stale
* @param scope
*/
struct ccn_charbuf* CCNGet::make_template(int allow_stale, int scope)
{
	struct ccn_charbuf *templ = ccn_charbuf_create();
	ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
	ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
	ccn_charbuf_append_closer(templ); /* </Name> */
	ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
	ccnb_append_number(templ, 1);
	ccn_charbuf_append_closer(templ); /* </MaxSuffixComponents> */
	if (allow_stale) {
		ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
		ccnb_append_number(templ, CCN_AOK_DEFAULT | CCN_AOK_STALE);
		ccn_charbuf_append_closer(templ); /* </AnswerOriginKind> */
	}
	if (scope >= 0 && scope <= 2) {
		ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", scope);
	}
	ccn_charbuf_append_closer(templ); /* </Interest> */
	return(templ);
}
예제 #18
0
파일: ccn_face_mgmt.c 프로젝트: Emat12/ccnx
/**
 * Marshal an internal face instance representation into ccnb form
 */
int
ccnb_append_face_instance(struct ccn_charbuf *c,
                          const struct ccn_face_instance *fi)
{
    int res;
    res = ccnb_element_begin(c, CCN_DTAG_FaceInstance);
    if (fi->action != NULL)
        res |= ccnb_tagged_putf(c, CCN_DTAG_Action, "%s",
                                fi->action);
    if (fi->ccnd_id_size != 0)
        res |= ccnb_append_tagged_blob(c, CCN_DTAG_PublisherPublicKeyDigest,
                                          fi->ccnd_id, fi->ccnd_id_size);
    if (fi->faceid != ~0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_FaceID, "%u",
                                   fi->faceid);
    if (fi->descr.ipproto >= 0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_IPProto, "%d",
                                   fi->descr.ipproto);
    if (fi->descr.address != NULL)
        res |= ccnb_tagged_putf(c, CCN_DTAG_Host, "%s",
                                   fi->descr.address);
    if (fi->descr.port != NULL)
        res |= ccnb_tagged_putf(c, CCN_DTAG_Port, "%s",
                                   fi->descr.port);    
    if (fi->descr.source_address != NULL)
        res |= ccnb_tagged_putf(c, CCN_DTAG_MulticastInterface, "%s",
                                   fi->descr.source_address);
    if (fi->descr.mcast_ttl >= 0 && fi->descr.mcast_ttl != 1)
        res |= ccnb_tagged_putf(c, CCN_DTAG_MulticastTTL, "%d",
                                   fi->descr.mcast_ttl);
    if (fi->lifetime >= 0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_FreshnessSeconds, "%d",
                                   fi->lifetime);    
    res |= ccnb_element_end(c);
    return(res);
}
예제 #19
0
파일: ccnpoke.c 프로젝트: IthacaDream/ccnx
int
main(int argc, char **argv)
{
    const char *progname = argv[0];
    struct ccn *ccn = NULL;
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *pname = NULL;
    struct ccn_charbuf *temp = NULL;
    struct ccn_charbuf *extopt = NULL;
    long expire = -1;
    int versioned = 0;
    size_t blocksize = 8*1024;
    int status = 0;
    int res;
    ssize_t read_res;
    unsigned char *buf = NULL;
    enum ccn_content_type content_type = CCN_CONTENT_DATA;
    struct ccn_closure in_interest = {.p=&incoming_interest};
    const char *postver = NULL;
    const char *key_uri = NULL;
    int force = 0;
    int verbose = 0;
    int timeout = -1;
    int setfinal = 0;
    int prefixcomps = -1;
    int fd;
    struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
    
    while ((res = getopt(argc, argv, "e:fhk:lvV:p:t:w:x:")) != -1) {
        switch (res) {
            case 'e':
                if (extopt == NULL)
                    extopt = ccn_charbuf_create();
                fd = open(optarg, O_RDONLY);
                if (fd < 0) {
                    perror(optarg);
                    exit(1);
                }
                for (;;) {
                    read_res = read(fd, ccn_charbuf_reserve(extopt, 64), 64);
                    if (read_res <= 0)
                        break;
                    extopt->length += read_res;
                }
                if (read_res < 0)
                    perror(optarg);
                close(fd);
                break;
            case 'f':
                force = 1;
                break;
            case 'l':
                setfinal = 1; // set FinalBlockID to last comp of name
                break;
            case 'k':
                key_uri = optarg;
                break;
            case 'p':
                prefixcomps = atoi(optarg);
                if (prefixcomps < 0)
                    usage(progname);
                break;
            case 'x':
                expire = atol(optarg);
                if (expire <= 0)
                    usage(progname);
                break;
            case 'v':
                verbose = 1;
                break;
            case 'V':
                versioned = 1;
                postver = optarg;
                if (0 == memcmp(postver, "%00", 3))
                    setfinal = 1;
                break;
            case 'w':
                timeout = atol(optarg);
                if (timeout <= 0)
                    usage(progname);
                timeout *= 1000;
                break;
            case 't':
                if (0 == strcasecmp(optarg, "DATA")) {
                    content_type = CCN_CONTENT_DATA;
                    break;
                }
                if (0 == strcasecmp(optarg, "ENCR")) {
                    content_type = CCN_CONTENT_ENCR;
                    break;
                }
                if (0 == strcasecmp(optarg, "GONE")) {
                    content_type = CCN_CONTENT_GONE;
                    break;
                }
                if (0 == strcasecmp(optarg, "KEY")) {
                    content_type = CCN_CONTENT_KEY;
                    break;
                }
                if (0 == strcasecmp(optarg, "LINK")) {
                    content_type = CCN_CONTENT_LINK;
                    break;
                }
                if (0 == strcasecmp(optarg, "NACK")) {
                    content_type = CCN_CONTENT_NACK;
                    break;
                }
                content_type = atoi(optarg);
                if (content_type > 0 && content_type <= 0xffffff)
                    break;
                fprintf(stderr, "Unknown content type %s\n", optarg);
                /* FALLTHRU */
            default:
            case 'h':
                usage(progname);
                break;
        }
    }
    argc -= optind;
    argv += optind;
    if (argv[0] == NULL)
        usage(progname);
    name = ccn_charbuf_create();
    res = ccn_name_from_uri(name, argv[0]);
    if (res < 0) {
        fprintf(stderr, "%s: bad ccn URI: %s\n", progname, argv[0]);
        exit(1);
    }
    if (argv[1] != NULL)
        fprintf(stderr, "%s warning: extra arguments ignored\n", progname);
    
    /* Preserve the original prefix, in case we add versioning,
     * but trim it down if requested for the interest filter registration
     */
    pname = ccn_charbuf_create();
    ccn_charbuf_append(pname, name->buf, name->length);
    if (prefixcomps >= 0) {
        res = ccn_name_chop(pname, NULL, prefixcomps);
        if (res < 0) {
            fprintf(stderr, "%s: unable to trim name to %d component%s.\n",
                    progname, prefixcomps, prefixcomps == 1 ? "" : "s");
            exit(1);
        }
    }
    /* Connect to ccnd */
    ccn = ccn_create();
    if (ccn_connect(ccn, NULL) == -1) {
        perror("Could not connect to ccnd");
        exit(1);
    }

    /* Read the actual user data from standard input */
    buf = calloc(1, blocksize);
    read_res = read_full(0, buf, blocksize);
    if (read_res < 0) {
        perror("read");
        read_res = 0;
        status = 1;
    }
        
    /* Tack on the version component if requested */
    if (versioned) {
        res = ccn_create_version(ccn, name, CCN_V_REPLACE | CCN_V_NOW | CCN_V_HIGH, 0, 0);
        if (res < 0) {
            fprintf(stderr, "%s: ccn_create_version() failed\n", progname);
            exit(1);
        }
        if (postver != NULL) {
            res = ccn_name_from_uri(name, postver);
            if (res < 0) {
                fprintf(stderr, "-V %s: invalid name suffix\n", postver);
                exit(0);
            }
        }
    }
    temp = ccn_charbuf_create();
    
    /* Ask for a FinalBlockID if appropriate. */
    if (setfinal)
        sp.sp_flags |= CCN_SP_FINAL_BLOCK;
    
    if (res < 0) {
        fprintf(stderr, "Failed to create signed_info (res == %d)\n", res);
        exit(1);
    }
    
    /* Set content type */
    sp.type = content_type;
    
    /* Set freshness */
    if (expire >= 0) {
        if (sp.template_ccnb == NULL) {
            sp.template_ccnb = ccn_charbuf_create();
            ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
        }
        else if (sp.template_ccnb->length > 0) {
            sp.template_ccnb->length--;
        }
        ccnb_tagged_putf(sp.template_ccnb, CCN_DTAG_FreshnessSeconds, "%ld", expire);
        sp.sp_flags |= CCN_SP_TEMPL_FRESHNESS;
        ccn_charbuf_append_closer(sp.template_ccnb);
    }
    
    /* Set key locator, if supplied */
    if (key_uri != NULL) {
        struct ccn_charbuf *c = ccn_charbuf_create();
        res = ccn_name_from_uri(c, key_uri);
        if (res < 0) {
            fprintf(stderr, "%s is not a valid ccnx URI\n", key_uri);
            exit(1);
        }
        if (sp.template_ccnb == NULL) {
            sp.template_ccnb = ccn_charbuf_create();
            ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
        }
        else if (sp.template_ccnb->length > 0) {
            sp.template_ccnb->length--;
        }
        ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyLocator, CCN_DTAG);
        ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyName, CCN_DTAG);
        ccn_charbuf_append(sp.template_ccnb, c->buf, c->length);
        ccn_charbuf_append_closer(sp.template_ccnb);
        ccn_charbuf_append_closer(sp.template_ccnb);
        sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR;
        ccn_charbuf_append_closer(sp.template_ccnb);
        ccn_charbuf_destroy(&c);
    }

    if (extopt != NULL && extopt->length > 0) {
        if (sp.template_ccnb == NULL) {
            sp.template_ccnb = ccn_charbuf_create();
            ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
        }
        else if (sp.template_ccnb->length > 0) {
            sp.template_ccnb->length--;
        }
        ccnb_append_tagged_blob(sp.template_ccnb, CCN_DTAG_ExtOpt,
                                extopt->buf, extopt->length);
        sp.sp_flags |= CCN_SP_TEMPL_EXT_OPT;
        ccn_charbuf_append_closer(sp.template_ccnb);
    }
    
    /* Create the signed content object, ready to go */
    temp->length = 0;
    res = ccn_sign_content(ccn, temp, name, &sp, buf, read_res);
    if (res != 0) {
        fprintf(stderr, "Failed to encode ContentObject (res == %d)\n", res);
        exit(1);
    }
    if (read_res == blocksize) {
        read_res = read_full(0, buf, 1);
        if (read_res == 1) {
            fprintf(stderr, "%s: warning - truncated data\n", argv[0]);
            status = 1;
        }
    }
    free(buf);
    buf = NULL;
    if (force) {
        /* At user request, send without waiting to see an interest */
        res = ccn_put(ccn, temp->buf, temp->length);
        if (res < 0) {
            fprintf(stderr, "ccn_put failed (res == %d)\n", res);
            exit(1);
        }
    }
    else {
        in_interest.data = temp;
        /* Set up a handler for interests */
        res = ccn_set_interest_filter(ccn, pname, &in_interest);
        if (res < 0) {
            fprintf(stderr, "Failed to register interest (res == %d)\n", res);
            exit(1);
        }
        res = ccn_run(ccn, timeout);
        if (in_interest.intdata == 0) {
            if (verbose)
                fprintf(stderr, "Nobody's interested\n");
            exit(1);
        }
    }
    
    if (verbose) {
        struct ccn_charbuf *uri = ccn_charbuf_create();
        uri->length = 0;
        ccn_uri_append(uri, name->buf, name->length, 1);
        printf("wrote %s\n", ccn_charbuf_as_string(uri));
        ccn_charbuf_destroy(&uri);
    }
    ccn_destroy(&ccn);
    ccn_charbuf_destroy(&name);
    ccn_charbuf_destroy(&pname);
    ccn_charbuf_destroy(&temp);
    ccn_charbuf_destroy(&sp.template_ccnb);
    ccn_charbuf_destroy(&extopt);
    exit(status);
}
예제 #20
0
파일: ccnls.c 프로젝트: Emat12/ccnx
int
main(int argc, char **argv)
{
    struct ccn *ccn = NULL;
    struct ccn_charbuf *c = NULL;
    struct ccn_charbuf *templ = NULL;
    struct upcalldata *data = NULL;
    int i;
    int n;
    int res;
    long counter = 0;
    struct ccn_closure *cl = NULL;
    int timeout_ms = 500;
    const char *env_timeout = getenv("CCN_LINGER");
    const char *env_verify = getenv("CCN_VERIFY");
    const char *env_scope = getenv("CCN_SCOPE");

    if (argv[1] == NULL || argv[2] != NULL)
        usage(argv[0]);

    if (env_timeout != NULL && (i = atoi(env_timeout)) > 0)
        timeout_ms = i * 1000;

    c = ccn_charbuf_create();
    res = ccn_name_from_uri(c, argv[1]);
    if (res < 0)
        usage(argv[0]);
        
    ccn = ccn_create();
    if (ccn_connect(ccn, NULL) == -1) {
        perror("Could not connect to ccnd");
        exit(1);
    }
    
    data = calloc(1, sizeof(*data));
    data->magic = 856372;
    data->warn = 1492;
    data->counter = &counter;
    data->option = 0;
    if (env_verify && *env_verify)
        data->option |= MUST_VERIFY;
    data->scope = -1;
    if (env_scope != NULL && (i = atoi(env_scope)) >= 0)
      data->scope = i;
    cl = calloc(1, sizeof(*cl));
    cl->p = &incoming_content;
    cl->data = data;
    if (data->scope > -1) {
        templ = ccn_charbuf_create();
        ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
        ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
        ccn_charbuf_append_closer(templ); /* </Name> */
        ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", data->scope);
        ccn_charbuf_append_closer(templ); /* </Interest> */
    }
    ccn_express_interest(ccn, c, cl, templ);
    ccn_charbuf_destroy(&templ);
    cl = NULL;
    data = NULL;
    for (i = 0;; i++) {
        n = counter;
        ccn_run(ccn, timeout_ms); /* stop if we run dry for 1/2 sec */
        fflush(stdout);
        if (counter == n)
            break;
    }
    ccn_destroy(&ccn);
    ccn_charbuf_destroy(&c);
    exit(0);
}
예제 #21
0
파일: ccnls.c 프로젝트: Emat12/ccnx
enum ccn_upcall_res
incoming_content(
    struct ccn_closure *selfp,
    enum ccn_upcall_kind kind,
    struct ccn_upcall_info *info)
{
    struct ccn_charbuf *c = NULL;
    struct ccn_charbuf *comp = NULL;
    struct ccn_charbuf *uri = NULL;
    struct ccn_charbuf *templ = NULL;
    const unsigned char *ccnb = NULL;
    size_t ccnb_size = 0;
    struct ccn_indexbuf *comps = NULL;
    int matched_comps = 0;
    int res;
    int i;
    struct upcalldata *data = selfp->data;
    
    if (data->magic != 856372) abort();
    if (kind == CCN_UPCALL_FINAL)
        return(CCN_UPCALL_RESULT_OK);
    if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
        return(CCN_UPCALL_RESULT_REEXPRESS);
    if (kind == CCN_UPCALL_CONTENT_UNVERIFIED) {
        if ((data->option & MUST_VERIFY) != 0)
        return(CCN_UPCALL_RESULT_VERIFY);
        }
    else if (kind != CCN_UPCALL_CONTENT) abort();
    
    ccnb = info->content_ccnb;
    ccnb_size = info->pco->offset[CCN_PCO_E];
    comps = info->content_comps;
    matched_comps = info->pi->prefix_comps;
    c = ccn_charbuf_create();
    uri = ccn_charbuf_create();
    templ = ccn_charbuf_create();
    /* note that comps->n is 1 greater than the number of explicit components */
    if (matched_comps > comps->n) {
        ccn_uri_append(c, ccnb, ccnb_size, 1);
        fprintf(stderr, "How did this happen?  %s\n", ccn_charbuf_as_string(uri));
        exit(1);
    }
    data->counter[0]++;
    /* Recover the same prefix as before */
    ccn_name_init(c);
    res = ccn_name_append_components(c, info->interest_ccnb,
                                     info->interest_comps->buf[0],
                                     info->interest_comps->buf[matched_comps]);
    if (res < 0) abort();
    
    comp = ccn_charbuf_create();
    ccn_name_init(comp);
    if (matched_comps + 1 == comps->n) {
        /* Reconstruct the implicit ContentObject digest component */
        ccn_digest_ContentObject(ccnb, info->pco);
        ccn_name_append(comp, info->pco->digest, info->pco->digest_bytes);
    }
    else if (matched_comps < comps->n) {
        ccn_name_append_components(comp, ccnb,
                                   comps->buf[matched_comps],
                                   comps->buf[matched_comps + 1]);
    }
    res = ccn_uri_append(uri, comp->buf, comp->length, 0);
    if (res < 0 || uri->length < 1)
        fprintf(stderr, "*** Error: ccnls line %d res=%d\n", __LINE__, res);
    else {
        if (uri->length == 1)
            ccn_charbuf_append(uri, ".", 1);
        printf("%s%s\n", ccn_charbuf_as_string(uri) + 1,
               kind == CCN_UPCALL_CONTENT ? " [verified]" : " [unverified]");
    }
    ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
    ccn_charbuf_append(templ, c->buf, c->length); /* Name */
    if (matched_comps == comps->n) {
        /* The interest supplied the digest component */
        ccn_charbuf_destroy(&comp);
        /*
         * We can't rely on the Exclude filter to keep from seeing this, so 
         * say that we need at least one more name component.
         */
        ccn_charbuf_append_tt(templ, CCN_DTAG_MinSuffixComponents, CCN_DTAG);
        ccn_charbuf_append_tt(templ, 1, CCN_UDATA);
        ccn_charbuf_append(templ, "1", 1);
        ccn_charbuf_append_closer(templ); /* </MinSuffixComponents> */
    }
    else {
        data->excl = realloc(data->excl, (data->n_excl + 1) * sizeof(data->excl[0]));
        data->excl[data->n_excl++] = comp;
        comp = NULL;
    }
    qsort(data->excl, data->n_excl, sizeof(data->excl[0]), &namecompare);
    ccn_charbuf_append_tt(templ, CCN_DTAG_Exclude, CCN_DTAG);
    for (i = 0; i < data->n_excl; i++) {
        comp = data->excl[i];
        if (comp->length < 4) abort();
        ccn_charbuf_append(templ, comp->buf + 1, comp->length - 2);
    }
    comp = NULL;
    ccn_charbuf_append_closer(templ); /* </Exclude> */
    ccnb_tagged_putf(templ, CCN_DTAG_AnswerOriginKind, "%d", CCN_AOK_CS);
    if (data->scope > -1)
       ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", data->scope);
    ccn_charbuf_append_closer(templ); /* </Interest> */
    if (templ->length > data->warn) {
        fprintf(stderr, "*** Interest packet is %d bytes\n", (int)templ->length);
        data->warn = data->warn * 8 / 5;
    }
    ccn_express_interest(info->h, c, selfp, templ);
    ccn_charbuf_destroy(&templ);
    ccn_charbuf_destroy(&c);
    ccn_charbuf_destroy(&uri);
    return(CCN_UPCALL_RESULT_OK);
}
예제 #22
0
int
main(int argc, char **argv)
{
    struct ccn *h = NULL;
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *null_name = NULL;
    struct ccn_charbuf *name_prefix = NULL;
    struct ccn_charbuf *newface = NULL;
    struct ccn_charbuf *prefixreg = NULL;
    struct ccn_charbuf *resultbuf = NULL;
    struct ccn_charbuf *temp = NULL;
    struct ccn_charbuf *templ = NULL;
    const unsigned char *ptr = NULL;
    size_t length = 0;
    const char *arg = NULL;
    const char *progname = NULL;
    struct ccn_parsed_ContentObject pcobuf = {0};
    struct ccn_face_instance face_instance_storage = {0};
    struct ccn_face_instance *face_instance = &face_instance_storage;
    struct ccn_forwarding_entry forwarding_entry_storage = {0};
    struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage;
    struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
    struct ccn_charbuf *keylocator_templ = NULL;
    struct ccn_keystore *keystore = NULL;
    long expire = -1;
    int ipproto;
    unsigned char ccndid_storage[32] = {0};
    const unsigned char *ccndid = NULL;
    size_t ccndid_size = 0;
    int res;
    int opt;

    progname = argv[0];
    while ((opt = getopt(argc, argv, "h")) != -1) {
        switch (opt) {
        case 'h':
        default:
            usage(progname);
        }
    }

    /* Sanity check the URI and argument count */
    arg = argv[optind];
    if (arg == NULL)
        usage(progname);
    name = ccn_charbuf_create();
    res = ccn_name_from_uri(name, arg);
    if (res < 0) {
        fprintf(stderr, "%s: bad ccn URI: %s\n", progname, arg);
        exit(1);
    }
    if (argc - optind < 3 || argc - optind > 4)
        usage(progname);

    h = ccn_create();
    res = ccn_connect(h, NULL);
    if (res < 0) {
        ccn_perror(h, "ccn_connect");
        exit(1);
    }

    newface = ccn_charbuf_create();
    temp = ccn_charbuf_create();
    templ = ccn_charbuf_create();
    keylocator_templ = ccn_charbuf_create();

    resultbuf = ccn_charbuf_create();
    name_prefix = ccn_charbuf_create();
    null_name = ccn_charbuf_create();
    CHKRES(ccn_name_init(null_name));

    keystore = ccn_keystore_create();

    /* We need to figure out our local ccnd's CCIDID */
    /* Set up our Interest template to indicate scope 1 */
    ccn_charbuf_reset(templ);
    ccnb_element_begin(templ, CCN_DTAG_Interest);
    ccnb_element_begin(templ, CCN_DTAG_Name);
    ccnb_element_end(templ);	/* </Name> */
    ccnb_tagged_putf(templ, CCN_DTAG_Scope, "1");
    ccnb_element_end(templ);	/* </Interest> */

    ccn_charbuf_reset(name);
    CHKRES(res = ccn_name_from_uri(name, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY"));
    CHKRES(res = ccn_get(h, name, templ, 200, resultbuf, &pcobuf, NULL, 0));
    res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest,
                              resultbuf->buf,
                              pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest],
                              pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest],
                              &ccndid, &ccndid_size);
    CHKRES(res);
    if (ccndid_size > sizeof(ccndid_storage))
        CHKRES(-1);
    memcpy(ccndid_storage, ccndid, ccndid_size);
    ccndid = ccndid_storage;

    face_instance->action = "newface";
    face_instance->ccnd_id = ccndid;
    face_instance->ccnd_id_size = ccndid_size;
    if (strcmp(argv[optind + 1], "tcp") == 0)
        ipproto = 6;
    else if (strcmp(argv[optind + 1], "udp") == 0)
        ipproto = 17;
    else
        ipproto = atoi(argv[optind + 1]);
    face_instance->descr.ipproto = ipproto; // XXX - 6 = tcp or 17 = udp
    face_instance->descr.address = argv[optind + 2];
    face_instance->descr.port = argv[optind + 3];
    if (face_instance->descr.port == NULL)
        face_instance->descr.port = CCN_DEFAULT_UNICAST_PORT;
    face_instance->descr.mcast_ttl = -1;
    face_instance->lifetime = (~0U) >> 1;

    CHKRES(res = ccnb_append_face_instance(newface, face_instance));
    temp->length = 0;
    CHKRES(ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", getenv("HOME")));
    res = ccn_keystore_init(keystore,
                            ccn_charbuf_as_string(temp),
                            "Th1s1sn0t8g00dp8ssw0rd.");
    CHKRES(res);

    ccnb_element_begin(keylocator_templ, CCN_DTAG_SignedInfo);
    ccnb_element_begin(keylocator_templ, CCN_DTAG_KeyLocator);
    ccnb_element_begin(keylocator_templ, CCN_DTAG_Key);
    CHKRES(ccn_append_pubkey_blob(keylocator_templ, ccn_keystore_public_key(keystore)));
    ccnb_element_end(keylocator_templ);	/* </Key> */
    ccnb_element_end(keylocator_templ);	/* </KeyLocator> */
    ccnb_element_end(keylocator_templ);    /* </SignedInfo> */
    sp.template_ccnb = keylocator_templ;
    sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR;
    sp.freshness = expire;
    ccn_charbuf_reset(temp);
    res = ccn_sign_content(h, temp, null_name, &sp,
                           newface->buf, newface->length);
    CHKRES(res);

    /* Create the new face */
    CHKRES(ccn_name_init(name));
    CHKRES(ccn_name_append_str(name, "ccnx"));
    CHKRES(ccn_name_append(name, ccndid, ccndid_size));
    CHKRES(ccn_name_append(name, "newface", 7));
    CHKRES(ccn_name_append(name, temp->buf, temp->length));
    res = ccn_get(h, name, templ, 1000, resultbuf, &pcobuf, NULL, 0);
    if (res < 0) {
        fprintf(stderr, "no response from face creation request\n");
        exit(1);
    }
    ptr = resultbuf->buf;
    length = resultbuf->length;
    res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length);
    CHKRES(res);
    face_instance = ccn_face_instance_parse(ptr, length);
    if (face_instance == NULL)
        CHKRES(res = -1);
    CHKRES(face_instance->faceid);

    /* Finally, register the prefix */
    ccn_charbuf_reset(name_prefix);
    CHKRES(ccn_name_from_uri(name_prefix, arg));
    forwarding_entry->action = "prefixreg";
    forwarding_entry->name_prefix = name_prefix;
    forwarding_entry->ccnd_id = ccndid;
    forwarding_entry->ccnd_id_size = ccndid_size;
    forwarding_entry->faceid = face_instance->faceid;
    forwarding_entry->flags = -1; /* let ccnd decide */
    forwarding_entry->lifetime = (~0U) >> 1;
    prefixreg = ccn_charbuf_create();
    CHKRES(res = ccnb_append_forwarding_entry(prefixreg, forwarding_entry));
    ccn_charbuf_reset(temp);
    res = ccn_sign_content(h, temp, null_name, &sp,
                           prefixreg->buf, prefixreg->length);
    CHKRES(res);
    CHKRES(ccn_name_init(name));
    CHKRES(ccn_name_append_str(name, "ccnx"));
    CHKRES(ccn_name_append(name, ccndid, ccndid_size));
    CHKRES(ccn_name_append_str(name, "prefixreg"));
    CHKRES(ccn_name_append(name, temp->buf, temp->length));
    res = ccn_get(h, name, templ, 1000, resultbuf, &pcobuf, NULL, 0);
    if (res < 0) {
        fprintf(stderr, "no response from prefix registration request\n");
        exit(1);
    }
    fprintf(stderr, "Prefix %s will be forwarded to face %d\n", arg, face_instance->faceid);

    /* We're about to exit, so don't bother to free everything. */
    ccn_destroy(&h);
    exit(res < 0);
}
예제 #23
0
/**
 * Append ChildSelector to partially constructed Interest, meaning
 * prefer to send rightmost available.
 */
static void
answer_highest(struct ccn_charbuf *templ)
{
    ccnb_tagged_putf(templ, CCN_DTAG_ChildSelector, "1");
}
예제 #24
0
/**
 * Create SignedInfo.
 *
 *
 * @param c is used to hold the result.
 * @param publisher_key_id points to the digest of the publisher key id.
 * @param publisher_key_id_size is the size in bytes(32) of the pub key digest
 * @param timestamp holds the timestamp, as a ccnb-encoded blob, or is NULL
          to use the current time.
 * @param type indicates the Type of the ContentObject.
 * @param freshness is the FreshnessSeconds value, or -1 to omit.
 * @param finalblockid holds the FinalBlockID, as a ccnb-encoded blob, or is
          NULL to omit.
 * @param key_locator is the ccnb-encoded KeyLocator element, or NULL to omit.
 * @returns 0 for success or -1 for error.
 */
int
ccn_signed_info_create(struct ccn_charbuf *c,
                       const void *publisher_key_id,	/* input, sha256 hash */
                       size_t publisher_key_id_size, 	/* input, 32 for sha256 hashes */
                       const struct ccn_charbuf *timestamp,/* input ccnb blob, NULL for "now" */
                       enum ccn_content_type type,	/* input */
                       int freshness,			/* input, -1 means omit */
                       const struct ccn_charbuf *finalblockid,  /* input, NULL means omit */
                       const struct ccn_charbuf *key_locator)	/* input, optional, ccnb encoded */
{
    int res = 0;
    const char fakepubkeyid[32] = {0};
 
    if (publisher_key_id != NULL && publisher_key_id_size != 32)
        return(-1);

    res |= ccn_charbuf_append_tt(c, CCN_DTAG_SignedInfo, CCN_DTAG);

    res |= ccn_charbuf_append_tt(c, CCN_DTAG_PublisherPublicKeyDigest, CCN_DTAG);
    if (publisher_key_id != NULL) {
        res |= ccn_charbuf_append_tt(c, publisher_key_id_size, CCN_BLOB);
        res |= ccn_charbuf_append(c, publisher_key_id, publisher_key_id_size);
    } else {
        /* XXX - obtain the default publisher key id and append it */
        res |= ccn_charbuf_append_tt(c, sizeof(fakepubkeyid), CCN_BLOB);
        res |= ccn_charbuf_append(c, fakepubkeyid, sizeof(fakepubkeyid));
    }
    res |= ccn_charbuf_append_closer(c);

    res |= ccn_charbuf_append_tt(c, CCN_DTAG_Timestamp, CCN_DTAG);
    if (timestamp != NULL)
        res |= ccn_charbuf_append_charbuf(c, timestamp);
    else
        res |= ccnb_append_now_blob(c, CCN_MARKER_NONE);
    res |= ccn_charbuf_append_closer(c);

    if (type != CCN_CONTENT_DATA) {
        res |= ccn_charbuf_append_tt(c, CCN_DTAG_Type, CCN_DTAG);
        res |= ccn_charbuf_append_tt(c, 3, CCN_BLOB);
        res |= ccn_charbuf_append_value(c, type, 3);
        res |= ccn_charbuf_append_closer(c);
    }

    if (freshness >= 0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_FreshnessSeconds, "%d", freshness);

    if (finalblockid != NULL) {
        res |= ccn_charbuf_append_tt(c, CCN_DTAG_FinalBlockID, CCN_DTAG);
        res |= ccn_charbuf_append_charbuf(c, finalblockid);
        res |= ccn_charbuf_append_closer(c);
    }

    if (key_locator != NULL) {
	/* key_locator is a sub-type that should already be encoded */
	res |= ccn_charbuf_append_charbuf(c, key_locator);
    }
    
    res |= ccn_charbuf_append_closer(c);

    return(res == 0 ? 0 : -1);
}