struct ccn_forwarding_entry * parse_ccn_forwarding_entry(struct ccndc_data *self, const char *cmd_uri, const char *cmd_flags, int freshness) { int res = 0; struct ccn_forwarding_entry *entry; entry= calloc(1, sizeof(*entry)); if (entry == NULL) { ccndc_warn(__LINE__, "Fatal error: memory allocation failed"); goto ExitOnError; } entry->name_prefix = ccn_charbuf_create(); if (entry->name_prefix == NULL) { ccndc_warn(__LINE__, "Fatal error: memory allocation failed"); goto ExitOnError; } // copy static info entry->ccnd_id = (const unsigned char *)self->ccnd_id; entry->ccnd_id_size = self->ccnd_id_size; /* we will be creating the face to either add/delete a prefix on it */ if (cmd_uri == NULL) { ccndc_warn(__LINE__, "command erro, missing CCNx URI\n"); goto ExitOnError; } res = ccn_name_from_uri(entry->name_prefix, cmd_uri); if (res < 0) { ccndc_warn(__LINE__, "command error, bad CCNx URI '%s'\n", cmd_uri); goto ExitOnError; } entry->flags = -1; if (cmd_flags != NULL && cmd_flags[0] != 0) { char *endptr; entry->flags = strtol(cmd_flags, &endptr, 10); if ((endptr != &cmd_flags[strlen(cmd_flags)]) || (entry->flags & ~CCN_FORW_PUBMASK) != 0) { ccndc_warn(__LINE__, "command error, invalid flags %s\n", cmd_flags); goto ExitOnError; } } entry->lifetime = freshness; return (entry); ExitOnError: ccn_forwarding_entry_destroy(&entry); return (NULL); }
enum ccn_upcall_res CcnLAC_fetchFaceidCb(struct ccn_closure* selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info* info) { CcnLAC self = (CcnLAC)selfp->data; switch (kind) { case CCN_UPCALL_FINAL: { free(selfp); return CCN_UPCALL_RESULT_OK; } case CCN_UPCALL_INTEREST_TIMED_OUT: { return CCN_UPCALL_RESULT_REEXPRESS; } case CCN_UPCALL_CONTENT_UNVERIFIED: case CCN_UPCALL_CONTENT_KEYMISSING: case CCN_UPCALL_CONTENT_RAW: case CCN_UPCALL_CONTENT: { struct ccn_forwarding_entry* fe = NULL; const unsigned char* fe_ccnb = NULL; size_t fe_ccnb_size = 0; int res = ccn_content_get_value(info->content_ccnb, info->pco->offset[CCN_PCO_E], info->pco, &fe_ccnb, &fe_ccnb_size); if (res == 0) fe = ccn_forwarding_entry_parse(fe_ccnb, fe_ccnb_size); if (fe != NULL) { self->faceid = fe->faceid; ccn_forwarding_entry_destroy(&fe); } else { self->error = true; } PollMgr_detach(self->pm, ccn_get_connection_fd(self->ccnh), &CcnLAC_initPollCb, self); void* emptyPDU = malloc(CCN_EMPTY_PDU_LENGTH); memcpy(emptyPDU, CCN_EMPTY_PDU, CCN_EMPTY_PDU_LENGTH); NBS_write(self->nbs, emptyPDU, 0, CCN_EMPTY_PDU_LENGTH, NULL); NBS_pollAttach(self->nbs, self->pm); return CCN_UPCALL_RESULT_OK; } default: { return CCN_UPCALL_RESULT_ERR; } } }
// creates a full structure without action, if proto == "face" only the // faceid (from cmd_host parameter) and lifetime will be filled in. struct ccn_face_instance * parse_ccn_face_instance(struct ccndc_data *self, const char *cmd_proto, const char *cmd_host, const char *cmd_port, const char *cmd_mcastttl, const char *cmd_mcastif, int freshness) { struct ccn_face_instance *entry; struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG)}; struct addrinfo mcasthints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG | AI_NUMERICHOST)}; struct addrinfo *raddrinfo = NULL; struct addrinfo *mcastifaddrinfo = NULL; char rhostnamebuf [NI_MAXHOST]; char rhostportbuf [NI_MAXSERV]; int off_address = -1, off_port = -1, off_source_address = -1; int res; int socktype; entry = calloc(1, sizeof(*entry)); if (entry == NULL) { ccndc_warn(__LINE__, "Fatal error: memory allocation failed"); goto ExitOnError; } // allocate storage for Face data entry->store = ccn_charbuf_create(); if (entry->store == NULL) { ccndc_warn(__LINE__, "Fatal error: memory allocation failed"); goto ExitOnError; } // copy static info entry->ccnd_id = (const unsigned char *)self->ccnd_id; entry->ccnd_id_size = self->ccnd_id_size; if (cmd_proto == NULL) { ccndc_warn(__LINE__, "command error, missing address type\n"); goto ExitOnError; } if (strcasecmp(cmd_proto, "udp") == 0) { entry->descr.ipproto = IPPROTO_UDP; socktype = SOCK_DGRAM; } else if (strcasecmp(cmd_proto, "tcp") == 0) { entry->descr.ipproto = IPPROTO_TCP; socktype = SOCK_STREAM; } else if (strcasecmp(cmd_proto, "face") == 0) { errno = 0; unsigned long faceid = strtoul(cmd_host, (char **)NULL, 10); if (errno == ERANGE || errno == EINVAL || faceid > UINT_MAX || faceid == 0) { ccndc_warn(__LINE__, "command error, face number invalid or out of range '%s'\n", cmd_host); goto ExitOnError; } entry->faceid = (unsigned) faceid; entry->lifetime = freshness; return (entry); } else { ccndc_warn(__LINE__, "command error, unrecognized address type '%s'\n", cmd_proto); goto ExitOnError; } if (cmd_host == NULL) { ccndc_warn(__LINE__, "command error, missing hostname\n"); goto ExitOnError; } if (cmd_port == NULL || cmd_port[0] == 0) cmd_port = CCN_DEFAULT_UNICAST_PORT; hints.ai_socktype = socktype; res = getaddrinfo(cmd_host, cmd_port, &hints, &raddrinfo); if (res != 0 || raddrinfo == NULL) { ccndc_warn(__LINE__, "command error, getaddrinfo for host [%s] port [%s]: %s\n", cmd_host, cmd_port, gai_strerror(res)); goto ExitOnError; } res = getnameinfo(raddrinfo->ai_addr, raddrinfo->ai_addrlen, rhostnamebuf, sizeof(rhostnamebuf), rhostportbuf, sizeof(rhostportbuf), NI_NUMERICHOST | NI_NUMERICSERV); freeaddrinfo(raddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, getnameinfo: %s\n", gai_strerror(res)); goto ExitOnError; } off_address = entry->store->length; res = ccn_charbuf_append(entry->store, rhostnamebuf, strlen(rhostnamebuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } off_port = entry->store->length; res = ccn_charbuf_append(entry->store, rhostportbuf, strlen(rhostportbuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } entry->descr.mcast_ttl = -1; if (cmd_mcastttl != NULL) { char *endptr; entry->descr.mcast_ttl = strtol(cmd_mcastttl, &endptr, 10); if ((endptr != &cmd_mcastttl[strlen(cmd_mcastttl)]) || entry->descr.mcast_ttl < 0 || entry->descr.mcast_ttl > 255) { ccndc_warn(__LINE__, "command error, invalid multicast ttl: %s\n", cmd_mcastttl); goto ExitOnError; } } if (cmd_mcastif != NULL) { res = getaddrinfo(cmd_mcastif, NULL, &mcasthints, &mcastifaddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, incorrect multicat interface [%s]: " "mcastifaddr getaddrinfo: %s\n", cmd_mcastif, gai_strerror(res)); goto ExitOnError; } res = getnameinfo(mcastifaddrinfo->ai_addr, mcastifaddrinfo->ai_addrlen, rhostnamebuf, sizeof(rhostnamebuf), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); freeaddrinfo(mcastifaddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, getnameinfo: %s\n", gai_strerror(res)); goto ExitOnError; } off_source_address = entry->store->length; res = ccn_charbuf_append(entry->store, rhostnamebuf, strlen(rhostnamebuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } } entry->descr.address = (const char *)(entry->store->buf + off_address); entry->descr.port = (const char *)(entry->store->buf + off_port); if (off_source_address >= 0) { entry->descr.source_address = (const char *)(entry->store->buf + off_source_address); } entry->lifetime = freshness; return entry; ExitOnError: ccn_face_instance_destroy(&entry); return (NULL); } struct ccn_face_instance * parse_ccn_face_instance_from_face(struct ccndc_data *self, const char *cmd_faceid) { struct ccn_face_instance *entry = calloc(1, sizeof(*entry)); // allocate storage for Face data entry->store = ccn_charbuf_create(); // copy static info entry->ccnd_id = (const unsigned char *)self->ccnd_id; entry->ccnd_id_size = self->ccnd_id_size; /* destroy a face - the URI field will hold the face number */ if (cmd_faceid == NULL) { ccndc_warn(__LINE__, "command error, missing face number for destroyface\n"); goto ExitOnError; } char *endptr; int facenumber = strtol(cmd_faceid, &endptr, 10); if ((endptr != &cmd_faceid[strlen(cmd_faceid)]) || facenumber < 0) { ccndc_warn(__LINE__, "command error invalid face number for destroyface: %d\n", facenumber); goto ExitOnError; } entry->faceid = facenumber; return entry; ExitOnError: ccn_face_instance_destroy(&entry); return (NULL); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // "private section /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ccndc_get_ccnd_id(struct ccndc_data *self) { struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; char ccndid_uri[] = "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY"; const unsigned char *ccndid_result; int res = 0; name = ccn_charbuf_create(); if (name == NULL) { ccndc_warn(__LINE__, "Unable to allocate storage for service locator name charbuf\n"); return -1; } resultbuf = ccn_charbuf_create(); if (resultbuf == NULL) { ccndc_warn(__LINE__, "Unable to allocate storage for result charbuf"); res = -1; goto Cleanup; } res = ccn_name_from_uri(name, ccndid_uri); if (res < 0) { ccndc_warn(__LINE__, "Unable to parse service locator URI for ccnd key"); goto Cleanup; } res = ccn_get(self->ccn_handle, name, self->local_scope_template, 4500, resultbuf, &pcobuf, NULL, 0); if (res < 0) { ccndc_warn(__LINE__, "Unable to get key from ccnd"); goto Cleanup; } res = ccn_ref_tagged_BLOB (CCN_DTAG_PublisherPublicKeyDigest, resultbuf->buf, pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest], pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest], &ccndid_result, &self->ccnd_id_size); if (res < 0) { ccndc_warn(__LINE__, "Unable to parse ccnd response for ccnd id"); goto Cleanup; } if (self->ccnd_id_size > sizeof (self->ccnd_id)) { ccndc_warn(__LINE__, "Incorrect size for ccnd id in response"); goto Cleanup; } memcpy(self->ccnd_id, ccndid_result, self->ccnd_id_size); Cleanup: ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&resultbuf); return (res); } struct ccn_face_instance * ccndc_do_face_action(struct ccndc_data *self, const char *action, struct ccn_face_instance *face_instance) { struct ccn_charbuf *newface = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *temp = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_face_instance *new_face_instance = NULL; const unsigned char *ptr = NULL; size_t length = 0; int res = 0; face_instance->action = action; /* Encode the given face instance */ newface = ccn_charbuf_create(); ON_NULL_CLEANUP(newface); ON_ERROR_CLEANUP(ccnb_append_face_instance(newface, face_instance)); temp = ccn_charbuf_create(); ON_NULL_CLEANUP(temp); res = ccn_sign_content(self->ccn_handle, temp, self->no_name, NULL, newface->buf, newface->length); ON_ERROR_CLEANUP(res); resultbuf = ccn_charbuf_create(); ON_NULL_CLEANUP(resultbuf); /* Construct the Interest name that will create the face */ name = ccn_charbuf_create(); ON_NULL_CLEANUP(name); ON_ERROR_CLEANUP(ccn_name_init(name)); ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx")); ON_ERROR_CLEANUP(ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size)); ON_ERROR_CLEANUP(ccn_name_append_str(name, face_instance->action)); ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(self->ccn_handle, name, self->local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length)); new_face_instance = ccn_face_instance_parse(ptr, length); ON_NULL_CLEANUP(new_face_instance); ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); return (new_face_instance); Cleanup: ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_face_instance_destroy(&new_face_instance); return (NULL); } int ccndc_do_prefix_action(struct ccndc_data *self, const char *action, struct ccn_forwarding_entry *forwarding_entry) { struct ccn_charbuf *temp = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *prefixreg = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_forwarding_entry *new_forwarding_entry = NULL; const unsigned char *ptr = NULL; size_t length = 0; int res; forwarding_entry->action = action; prefixreg = ccn_charbuf_create(); ON_NULL_CLEANUP(prefixreg); ON_ERROR_CLEANUP(ccnb_append_forwarding_entry(prefixreg, forwarding_entry)); temp = ccn_charbuf_create(); ON_NULL_CLEANUP(temp); res = ccn_sign_content(self->ccn_handle, temp, self->no_name, NULL, prefixreg->buf, prefixreg->length); ON_ERROR_CLEANUP(res); resultbuf = ccn_charbuf_create(); ON_NULL_CLEANUP(resultbuf); name = ccn_charbuf_create(); ON_ERROR_CLEANUP(ccn_name_init(name)); ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx")); ON_ERROR_CLEANUP(ccn_name_append(name, forwarding_entry->ccnd_id, forwarding_entry->ccnd_id_size)); ON_ERROR_CLEANUP(ccn_name_append_str(name, forwarding_entry->action)); ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(self->ccn_handle, name, self->local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length)); new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length); ON_NULL_CLEANUP(new_forwarding_entry); res = new_forwarding_entry->faceid; ccn_forwarding_entry_destroy(&new_forwarding_entry); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return (res); /* This is where ON_ERROR_CLEANUP sends us in case of an error * and we must free any storage we allocated before returning. */ Cleanup: ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return (-1); }
int ccndc_srv(struct ccndc_data *self, const unsigned char *domain, size_t domain_size) { char *proto = NULL; char *host = NULL; int port = 0; char port_str[10]; struct ccn_charbuf *uri; struct ccn_charbuf *uri_auto; struct ccn_face_instance *face; struct ccn_face_instance *newface; struct ccn_forwarding_entry *prefix; struct ccn_forwarding_entry *prefix_auto; int res; res = ccndc_query_srv(domain, domain_size, &host, &port, &proto); if (res < 0) { return -1; } uri = ccn_charbuf_create(); ccn_charbuf_append_string(uri, "ccnx:/"); if (domain_size != 0) { ccn_uri_append_percentescaped(uri, domain, domain_size); } snprintf (port_str, sizeof(port_str), "%d", port); /* now process the results */ /* pflhead, lineno=0, "add" "ccnx:/asdfasdf.com/" "tcp|udp", host, portstring, NULL NULL NULL */ ccndc_note(__LINE__, " >>> trying: add %s %s %s %s <<<\n", ccn_charbuf_as_string(uri), proto, host, port_str); face = parse_ccn_face_instance(self, proto, host, port_str, NULL, NULL, (~0U) >> 1); prefix = parse_ccn_forwarding_entry(self, ccn_charbuf_as_string(uri), NULL, self->lifetime); if (face == NULL || prefix == NULL) { res = -1; goto Cleanup; } // crazy operation // First. "Create" face, which will do nothing if face already exists // Second. Destroy the face // Third. Create face for real newface = ccndc_do_face_action(self, "newface", face); if (newface == NULL) { ccndc_warn(__LINE__, "Cannot create/lookup face"); res = -1; goto Cleanup; } face->faceid = newface->faceid; ccn_face_instance_destroy(&newface); newface = ccndc_do_face_action(self, "destroyface", face); if (newface == NULL) { ccndc_warn(__LINE__, "Cannot destroy face"); } else { ccn_face_instance_destroy(&newface); } newface = ccndc_do_face_action(self, "newface", face); if (newface == NULL) { ccndc_warn(__LINE__, "Cannot create/lookup face"); res = -1; goto Cleanup; } prefix->faceid = newface->faceid; ccn_face_instance_destroy(&newface); res = ccndc_do_prefix_action(self, "prefixreg", prefix); if (res < 0) { ccndc_warn(__LINE__, "Cannot register prefix [%s]\n", ccn_charbuf_as_string(uri)); } uri_auto = ccn_charbuf_create(); ccn_charbuf_append_string(uri_auto, "ccnx:/autoconf-route"); prefix_auto = parse_ccn_forwarding_entry(self, ccn_charbuf_as_string(uri_auto), NULL, self->lifetime); if (prefix_auto == NULL) { res = -1; goto Cleanup; } prefix_auto->faceid = prefix->faceid; res = ccndc_do_prefix_action(self, "prefixreg", prefix_auto); if (res < 0) { ccndc_warn(__LINE__, "Cannot register prefix_auto [%s]\n", ccn_charbuf_as_string(uri_auto)); } Cleanup: free(host); ccn_charbuf_destroy(&uri); ccn_charbuf_destroy(&uri_auto); ccn_face_instance_destroy(&face); ccn_forwarding_entry_destroy(&prefix); ccn_forwarding_entry_destroy(&prefix_auto); return res; }
/* * uri (udp|tcp) host [port [flags [mcastttl [mcastif]]]]) * uri face faceid */ int ccndc_renew(struct ccndc_data *self, int check_only, const char *cmd_orig) { int ret_code = -1; char *cmd, *cmd_token; char *cmd_uri = NULL; char *cmd_proto = NULL; char *cmd_host = NULL; char *cmd_port = NULL; char *cmd_flags = NULL; char *cmd_mcastttl = NULL; char *cmd_mcastif = NULL; struct ccn_face_instance *face = NULL; struct ccn_face_instance *newface = NULL; struct ccn_forwarding_entry *prefix = NULL; if (cmd_orig == NULL) { ccndc_warn(__LINE__, "command error\n"); return -1; } cmd = strdup(cmd_orig); if (cmd == NULL) { ccndc_warn(__LINE__, "Cannot allocate memory for copy of the command\n"); return -1; } cmd_token = cmd; GET_NEXT_TOKEN(cmd_token, cmd_uri); GET_NEXT_TOKEN(cmd_token, cmd_proto); GET_NEXT_TOKEN(cmd_token, cmd_host); GET_NEXT_TOKEN(cmd_token, cmd_port); GET_NEXT_TOKEN(cmd_token, cmd_flags); GET_NEXT_TOKEN(cmd_token, cmd_mcastttl); GET_NEXT_TOKEN(cmd_token, cmd_mcastif); // perform sanity checking face = parse_ccn_face_instance(self, cmd_proto, cmd_host, cmd_port, cmd_mcastttl, cmd_mcastif, (~0U) >> 1); prefix = parse_ccn_forwarding_entry(self, cmd_uri, cmd_flags, self->lifetime); if (face == NULL || prefix == NULL) goto Cleanup; if (!check_only) { // look up the old face ("queryface" would be useful) newface = ccndc_do_face_action(self, "newface", face); if (newface == NULL) { ccndc_warn(__LINE__, "Cannot create/lookup face"); goto Cleanup; } face->faceid = newface->faceid; ccn_face_instance_destroy(&newface); // destroy the old face newface = ccndc_do_face_action(self, "destroyface", face); if (newface == NULL) { ccndc_warn(__LINE__, "Cannot destroy face %d or the face does not exist\n", face->faceid); goto Cleanup; } ccn_face_instance_destroy(&newface); // recreate the face newface = ccndc_do_face_action(self, "newface", face); if (newface == NULL) { ccndc_warn(__LINE__, "Cannot create/lookup face"); goto Cleanup; } prefix->faceid = newface->faceid; ccn_face_instance_destroy(&newface); // and add the prefix to it ret_code = ccndc_do_prefix_action(self, "prefixreg", prefix); if (ret_code < 0) { ccndc_warn(__LINE__, "Cannot register prefix [%s]\n", cmd_uri); goto Cleanup; } } ret_code = 0; Cleanup: ccn_face_instance_destroy(&face); ccn_forwarding_entry_destroy(&prefix); free(cmd); return (ret_code); }
int ccndc_del(struct ccndc_data *self, int check_only, const char *cmd_orig) { int ret_code = -1; char *cmd, *cmd_token; char *cmd_uri = NULL; char *cmd_proto = NULL; char *cmd_host = NULL; char *cmd_port = NULL; char *cmd_flags = NULL; char *cmd_mcastttl = NULL; char *cmd_mcastif = NULL; struct ccn_face_instance *face = NULL; struct ccn_face_instance *newface = NULL; struct ccn_forwarding_entry *prefix = NULL; if (cmd_orig == NULL) { ccndc_warn(__LINE__, "command error\n"); return -1; } cmd = strdup(cmd_orig); if (cmd == NULL) { ccndc_warn(__LINE__, "Cannot allocate memory for copy of the command\n"); return -1; } cmd_token = cmd; GET_NEXT_TOKEN(cmd_token, cmd_uri); GET_NEXT_TOKEN(cmd_token, cmd_proto); GET_NEXT_TOKEN(cmd_token, cmd_host); GET_NEXT_TOKEN(cmd_token, cmd_port); GET_NEXT_TOKEN(cmd_token, cmd_flags); GET_NEXT_TOKEN(cmd_token, cmd_mcastttl); GET_NEXT_TOKEN(cmd_token, cmd_mcastif); face = parse_ccn_face_instance(self, cmd_proto, cmd_host, cmd_port, cmd_mcastttl, cmd_mcastif, (~0U) >> 1); prefix = parse_ccn_forwarding_entry(self, cmd_uri, cmd_flags, (~0U) >> 1); if (face == NULL || prefix == NULL) goto Cleanup; if (!check_only) { if (0 != strcasecmp(cmd_proto, "face")) { newface = ccndc_do_face_action(self, "newface", face); if (newface == NULL) { ccndc_warn(__LINE__, "Cannot create/lookup face"); goto Cleanup; } prefix->faceid = newface->faceid; ccn_face_instance_destroy(&newface); } else { prefix->faceid = face->faceid; } ret_code = ccndc_do_prefix_action(self, "unreg", prefix); if (ret_code < 0) { ccndc_warn(__LINE__, "Cannot unregister prefix [%s]\n", cmd_uri); goto Cleanup; } } ret_code = 0; Cleanup: ccn_face_instance_destroy(&face); ccn_forwarding_entry_destroy(&prefix); free(cmd); return (ret_code); }
/** * * Bind a prefix to a face * */ static int register_unregister_prefix(struct ccn *h, struct ccn_charbuf *local_scope_template, struct ccn_charbuf *no_name, struct ccn_charbuf *name_prefix, struct ccn_face_instance *face_instance, int operation) { struct ccn_charbuf *temp = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *prefixreg = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_forwarding_entry forwarding_entry_storage = {0}; struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage; struct ccn_forwarding_entry *new_forwarding_entry; const unsigned char *ptr = NULL; size_t length = 0; int res; /* Register or unregister the prefix */ forwarding_entry->action = (operation == OP_REG) ? "prefixreg" : "unreg"; forwarding_entry->name_prefix = name_prefix; forwarding_entry->ccnd_id = face_instance->ccnd_id; forwarding_entry->ccnd_id_size = face_instance->ccnd_id_size; forwarding_entry->faceid = face_instance->faceid; forwarding_entry->flags = -1; forwarding_entry->lifetime = 2100; prefixreg = ccn_charbuf_create(); ccnb_append_forwarding_entry(prefixreg, forwarding_entry); temp = ccn_charbuf_create(); res = ccn_sign_content(h, temp, no_name, NULL, prefixreg->buf, prefixreg->length); resultbuf = ccn_charbuf_create(); /* construct Interest containing prefixreg request */ name = ccn_charbuf_create(); ccn_name_init(name); ccn_name_append_str(name, "ccnx"); ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size); ccn_name_append_str(name, (operation == OP_REG) ? "prefixreg" : "unreg"); ccn_name_append(name, temp->buf, temp->length); /* send Interest, get Data */ res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length); ON_ERROR_CLEANUP(res); /* extract new forwarding entry from Data */ new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length); ON_NULL_CLEANUP(new_forwarding_entry); res = new_forwarding_entry->faceid; ccn_forwarding_entry_destroy(&new_forwarding_entry); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return res; cleanup: ccn_forwarding_entry_destroy(&new_forwarding_entry); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return -1; }
struct ccn_forwarding_entry * ccn_forwarding_entry_parse(const unsigned char *p, size_t size) { struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, p, size); struct ccn_charbuf *store = ccn_charbuf_create(); struct ccn_forwarding_entry *result; const unsigned char *val; size_t sz; size_t start; size_t end; int action_off = -1; int ccnd_id_off = -1; if (store == NULL) return(NULL); result = calloc(1, sizeof(*result)); if (result == NULL) { ccn_charbuf_destroy(&store); return(NULL); } if (ccn_buf_match_dtag(d, CCN_DTAG_ForwardingEntry)) { ccn_buf_advance(d); action_off = ccn_parse_tagged_string(d, CCN_DTAG_Action, store); if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) { result->name_prefix = ccn_charbuf_create(); start = d->decoder.token_index; ccn_parse_Name(d, NULL); end = d->decoder.token_index; ccn_charbuf_append(result->name_prefix, p + start, end - start); } else result->name_prefix = NULL; if (ccn_buf_match_dtag(d, CCN_DTAG_PublisherPublicKeyDigest)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &val, &sz)) { ccn_buf_advance(d); if (sz != 32) d->decoder.state = -__LINE__; } ccn_buf_check_close(d); if (d->decoder.state >= 0) { ccnd_id_off = store->length; ccn_charbuf_append(store, val, sz); result->ccnd_id_size = sz; } } result->faceid = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FaceID); result->flags = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_ForwardingFlags); result->lifetime = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FreshnessSeconds); ccn_buf_check_close(d); } else d->decoder.state = -__LINE__; if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state) || store->length > sizeof(result->store)) ccn_forwarding_entry_destroy(&result); else { char *b = (char *)result->store; memcpy(b, store->buf, store->length); result->action = (action_off == -1) ? NULL : b + action_off; result->ccnd_id = (ccnd_id_off == -1) ? NULL : result->store + ccnd_id_off; } ccn_charbuf_destroy(&store); return(result); }