00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <arpa/inet.h>
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <poll.h>
00024 #include <signal.h>
00025 #include <stdint.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <sys/socket.h>
00030 #include <sys/stat.h>
00031 #include <sys/time.h>
00032 #include <sys/types.h>
00033 #include <sys/un.h>
00034 #include <unistd.h>
00035 #include <openssl/evp.h>
00036
00037 #include <ccn/ccn.h>
00038 #include <ccn/ccn_private.h>
00039 #include <ccn/ccnd.h>
00040 #include <ccn/charbuf.h>
00041 #include <ccn/coding.h>
00042 #include <ccn/digest.h>
00043 #include <ccn/hashtb.h>
00044 #include <ccn/reg_mgmt.h>
00045 #include <ccn/schedule.h>
00046 #include <ccn/signing.h>
00047 #include <ccn/keystore.h>
00048 #include <ccn/uri.h>
00049
00050
00051 struct interests_by_prefix;
00052 struct expressed_interest;
00053 struct interest_filter;
00054 struct ccn_reg_closure;
00055
00056
00057
00058
00059 struct ccn {
00060 int sock;
00061 size_t outbufindex;
00062 struct ccn_charbuf *interestbuf;
00063 struct ccn_charbuf *inbuf;
00064 struct ccn_charbuf *outbuf;
00065 struct ccn_charbuf *ccndid;
00066 struct hashtb *interests_by_prefix;
00067 struct hashtb *interest_filters;
00068 struct ccn_skeleton_decoder decoder;
00069 struct ccn_indexbuf *scratch_indexbuf;
00070 struct hashtb *keys;
00071 struct hashtb *keystores;
00072 struct ccn_charbuf *default_pubid;
00073 struct ccn_schedule *schedule;
00074 struct timeval now;
00075 int timeout;
00076 int refresh_us;
00077 int err;
00078 int errline;
00079 int verbose_error;
00080 int tap;
00081 int running;
00082 int defer_verification;
00083 };
00084
00085 struct interests_by_prefix {
00086 struct expressed_interest *list;
00087 };
00088
00089 struct expressed_interest {
00090 int magic;
00091 struct timeval lasttime;
00092 struct ccn_closure *action;
00093 unsigned char *interest_msg;
00094 size_t size;
00095 int target;
00096 int outstanding;
00097 int lifetime_us;
00098 struct ccn_charbuf *wanted_pub;
00099 struct expressed_interest *next;
00100 };
00101
00102
00103
00104
00105 struct interest_filter {
00106 struct ccn_closure *action;
00107 struct ccn_reg_closure *ccn_reg_closure;
00108 struct timeval expiry;
00109 int flags;
00110 };
00111 #define CCN_FORW_WAITING_CCNDID (1<<30)
00112
00113 struct ccn_reg_closure {
00114 struct ccn_closure action;
00115 struct interest_filter *interest_filter;
00116 };
00117
00118
00119
00120 #define NOTE_ERR(h, e) (h->err = (e), h->errline = __LINE__, ccn_note_err(h))
00121 #define NOTE_ERRNO(h) NOTE_ERR(h, errno)
00122
00123 #define THIS_CANNOT_HAPPEN(h) \
00124 do { NOTE_ERR(h, -73); ccn_perror(h, "Can't happen");} while (0)
00125
00126 #define XXX \
00127 do { NOTE_ERR(h, -76); ccn_perror(h, "Please write some more code here"); } while (0)
00128
00129
00130
00131 static void ccn_refresh_interest(struct ccn *, struct expressed_interest *);
00132 static void ccn_initiate_prefix_reg(struct ccn *,
00133 const void *, size_t,
00134 struct interest_filter *);
00135 static void finalize_pkey(struct hashtb_enumerator *e);
00136 static void finalize_keystore(struct hashtb_enumerator *e);
00137 static int ccn_pushout(struct ccn *h);
00138 static void update_ifilt_flags(struct ccn *, struct interest_filter *, int);
00139 static int update_multifilt(struct ccn *,
00140 struct interest_filter *,
00141 struct ccn_closure *,
00142 int);
00143
00144
00145
00146 static int
00147 tv_earlier(const struct timeval *a, const struct timeval *b)
00148 {
00149 if (a->tv_sec > b->tv_sec)
00150 return(0);
00151 if (a->tv_sec < b->tv_sec)
00152 return(1);
00153 return(a->tv_usec < b->tv_usec);
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163 void
00164 ccn_perror(struct ccn *h, const char *s)
00165 {
00166 const char *dlm = ": ";
00167 if (s == NULL) {
00168 if (h->err > 0)
00169 s = strerror(h->err);
00170 else
00171 dlm = s = "";
00172 }
00173
00174 fprintf(stderr, "ccn_client.c:%d[%d] - error %d%s%s\n",
00175 h->errline, (int)getpid(), h->err, dlm, s);
00176 }
00177
00178 static int
00179 ccn_note_err(struct ccn *h)
00180 {
00181 if (h->verbose_error)
00182 ccn_perror(h, NULL);
00183 return(-1);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 int
00193 ccn_seterror(struct ccn *h, int error_code)
00194 {
00195 if (h == NULL)
00196 return(-1);
00197 h->err = error_code;
00198 h->errline = 0;
00199 if (error_code != 0)
00200 ccn_note_err(h);
00201 return(-1);
00202 }
00203
00204
00205
00206
00207
00208
00209 int
00210 ccn_geterror(struct ccn *h)
00211 {
00212 if (h == NULL)
00213 return(0);
00214 return(h->err);
00215 }
00216
00217 static struct ccn_indexbuf *
00218 ccn_indexbuf_obtain(struct ccn *h)
00219 {
00220 struct ccn_indexbuf *c = h->scratch_indexbuf;
00221 if (c == NULL)
00222 return(ccn_indexbuf_create());
00223 h->scratch_indexbuf = NULL;
00224 c->n = 0;
00225 return(c);
00226 }
00227
00228 static void
00229 ccn_indexbuf_release(struct ccn *h, struct ccn_indexbuf *c)
00230 {
00231 c->n = 0;
00232 if (h->scratch_indexbuf == NULL)
00233 h->scratch_indexbuf = c;
00234 else
00235 ccn_indexbuf_destroy(&c);
00236 }
00237
00238
00239
00240
00241
00242
00243 static void
00244 ccn_replace_handler(struct ccn *h,
00245 struct ccn_closure **dstp,
00246 struct ccn_closure *src)
00247 {
00248 struct ccn_closure *old = *dstp;
00249 if (src == old)
00250 return;
00251 if (src != NULL)
00252 src->refcount++;
00253 *dstp = src;
00254 if (old != NULL && (--(old->refcount)) == 0) {
00255 struct ccn_upcall_info info = { 0 };
00256 info.h = h;
00257 (old->p)(old, CCN_UPCALL_FINAL, &info);
00258 }
00259 }
00260
00261
00262
00263
00264
00265
00266
00267 struct ccn *
00268 ccn_create(void)
00269 {
00270 struct ccn *h;
00271 const char *s;
00272 struct hashtb_param param = {0};
00273
00274 h = calloc(1, sizeof(*h));
00275 if (h == NULL)
00276 return(h);
00277 param.finalize_data = h;
00278 h->sock = -1;
00279 h->interestbuf = ccn_charbuf_create();
00280 param.finalize = &finalize_pkey;
00281 h->keys = hashtb_create(sizeof(struct ccn_pkey *), ¶m);
00282 param.finalize = &finalize_keystore;
00283 h->keystores = hashtb_create(sizeof(struct ccn_keystore *), ¶m);
00284 s = getenv("CCN_DEBUG");
00285 h->verbose_error = (s != NULL && s[0] != 0);
00286 s = getenv("CCN_TAP");
00287 if (s != NULL && s[0] != 0) {
00288 char tap_name[255];
00289 struct timeval tv;
00290 gettimeofday(&tv, NULL);
00291 if (snprintf(tap_name, 255, "%s-%d-%d-%d", s, (int)getpid(),
00292 (int)tv.tv_sec, (int)tv.tv_usec) >= 255) {
00293 fprintf(stderr, "CCN_TAP path is too long: %s\n", s);
00294 } else {
00295 h->tap = open(tap_name, O_WRONLY|O_APPEND|O_CREAT, S_IRWXU);
00296 if (h->tap == -1) {
00297 NOTE_ERRNO(h);
00298 ccn_perror(h, "Unable to open CCN_TAP file");
00299 }
00300 else
00301 fprintf(stderr, "CCN_TAP writing to %s\n", tap_name);
00302 }
00303 } else
00304 h->tap = -1;
00305 h->defer_verification = 0;
00306 OpenSSL_add_all_algorithms();
00307 return(h);
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 int
00331 ccn_defer_verification(struct ccn *h, int defer)
00332 {
00333 int old;
00334
00335 if (h == NULL || defer > 1 || defer < -1)
00336 return(-1);
00337 old = h->defer_verification;
00338 if (defer >= 0)
00339 h->defer_verification = defer;
00340 return(old);
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350 int
00351 ccn_connect(struct ccn *h, const char *name)
00352 {
00353 struct sockaddr_un addr = {0};
00354 int res;
00355 if (h == NULL)
00356 return(-1);
00357 h->err = 0;
00358 if (h->sock != -1)
00359 return(NOTE_ERR(h, EINVAL));
00360 addr.sun_family = AF_UNIX;
00361 if (name == NULL || name[0] == 0)
00362 ccn_setup_sockaddr_un(NULL, &addr);
00363 else {
00364 addr.sun_family = AF_UNIX;
00365 strncpy(addr.sun_path, name, sizeof(addr.sun_path));
00366 }
00367 h->sock = socket(AF_UNIX, SOCK_STREAM, 0);
00368 if (h->sock == -1)
00369 return(NOTE_ERRNO(h));
00370 res = connect(h->sock, (struct sockaddr *)&addr, sizeof(addr));
00371 if (res == -1)
00372 return(NOTE_ERRNO(h));
00373 res = fcntl(h->sock, F_SETFL, O_NONBLOCK);
00374 if (res == -1)
00375 return(NOTE_ERRNO(h));
00376 return(h->sock);
00377 }
00378
00379 int
00380 ccn_get_connection_fd(struct ccn *h)
00381 {
00382 return(h->sock);
00383 }
00384
00385 int
00386 ccn_disconnect(struct ccn *h)
00387 {
00388 int res;
00389 res = ccn_pushout(h);
00390 if (res == 1) {
00391 res = fcntl(h->sock, F_SETFL, 0);
00392 if (res == 0)
00393 ccn_pushout(h);
00394 }
00395 ccn_charbuf_destroy(&h->inbuf);
00396 ccn_charbuf_destroy(&h->outbuf);
00397 res = close(h->sock);
00398 h->sock = -1;
00399 if (res == -1)
00400 return(NOTE_ERRNO(h));
00401 return(0);
00402 }
00403
00404 static void
00405 ccn_gripe(struct expressed_interest *i)
00406 {
00407 fprintf(stderr, "BOTCH - (struct expressed_interest *)%p has bad magic value\n", (void *)i);
00408 }
00409
00410 static void
00411 replace_interest_msg(struct expressed_interest *interest,
00412 struct ccn_charbuf *cb)
00413 {
00414 if (interest->magic != 0x7059e5f4) {
00415 ccn_gripe(interest);
00416 return;
00417 }
00418 if (interest->interest_msg != NULL)
00419 free(interest->interest_msg);
00420 interest->interest_msg = NULL;
00421 interest->size = 0;
00422 if (cb != NULL && cb->length > 0) {
00423 interest->interest_msg = calloc(1, cb->length);
00424 if (interest->interest_msg != NULL) {
00425 memcpy(interest->interest_msg, cb->buf, cb->length);
00426 interest->size = cb->length;
00427 }
00428 }
00429 }
00430
00431 static struct expressed_interest *
00432 ccn_destroy_interest(struct ccn *h, struct expressed_interest *i)
00433 {
00434 struct expressed_interest *ans = i->next;
00435 if (i->magic != 0x7059e5f4) {
00436 ccn_gripe(i);
00437 return(NULL);
00438 }
00439 ccn_replace_handler(h, &(i->action), NULL);
00440 replace_interest_msg(i, NULL);
00441 ccn_charbuf_destroy(&i->wanted_pub);
00442 i->magic = -1;
00443 free(i);
00444 return(ans);
00445 }
00446
00447 void
00448 ccn_check_interests(struct expressed_interest *list)
00449 {
00450 struct expressed_interest *ie;
00451 for (ie = list; ie != NULL; ie = ie->next) {
00452 if (ie->magic != 0x7059e5f4) {
00453 ccn_gripe(ie);
00454 abort();
00455 }
00456 }
00457 }
00458
00459 void
00460 ccn_clean_interests_by_prefix(struct ccn *h, struct interests_by_prefix *entry)
00461 {
00462 struct expressed_interest *ie;
00463 struct expressed_interest *next;
00464 struct expressed_interest **ip;
00465 ccn_check_interests(entry->list);
00466 ip = &(entry->list);
00467 for (ie = entry->list; ie != NULL; ie = next) {
00468 next = ie->next;
00469 if (ie->action == NULL)
00470 ccn_destroy_interest(h, ie);
00471 else {
00472 (*ip) = ie;
00473 ip = &(ie->next);
00474 }
00475 }
00476 (*ip) = NULL;
00477 ccn_check_interests(entry->list);
00478 }
00479
00480 void
00481 ccn_destroy(struct ccn **hp)
00482 {
00483 struct hashtb_enumerator ee;
00484 struct hashtb_enumerator *e = ⅇ
00485 struct ccn *h = *hp;
00486 if (h == NULL)
00487 return;
00488 ccn_schedule_destroy(&h->schedule);
00489 ccn_disconnect(h);
00490 if (h->interests_by_prefix != NULL) {
00491 for (hashtb_start(h->interests_by_prefix, e); e->data != NULL; hashtb_next(e)) {
00492 struct interests_by_prefix *entry = e->data;
00493 while (entry->list != NULL)
00494 entry->list = ccn_destroy_interest(h, entry->list);
00495 }
00496 hashtb_end(e);
00497 hashtb_destroy(&(h->interests_by_prefix));
00498 }
00499 if (h->interest_filters != NULL) {
00500 for (hashtb_start(h->interest_filters, e); e->data != NULL; hashtb_next(e)) {
00501 struct interest_filter *i = e->data;
00502 ccn_replace_handler(h, &(i->action), NULL);
00503 }
00504 hashtb_end(e);
00505 hashtb_destroy(&(h->interest_filters));
00506 }
00507 hashtb_destroy(&(h->keys));
00508 hashtb_destroy(&(h->keystores));
00509 ccn_charbuf_destroy(&h->interestbuf);
00510 ccn_charbuf_destroy(&h->inbuf);
00511 ccn_charbuf_destroy(&h->outbuf);
00512 ccn_indexbuf_destroy(&h->scratch_indexbuf);
00513 ccn_charbuf_destroy(&h->default_pubid);
00514 ccn_charbuf_destroy(&h->ccndid);
00515 if (h->tap != -1)
00516 close(h->tap);
00517 free(h);
00518 *hp = NULL;
00519 EVP_cleanup();
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529 static int
00530 ccn_check_namebuf(struct ccn *h, struct ccn_charbuf *namebuf, int prefix_comps,
00531 int omit_possible_digest)
00532 {
00533 struct ccn_buf_decoder decoder;
00534 struct ccn_buf_decoder *d;
00535 int i = 0;
00536 int ans = 0;
00537 int prev_ans = 0;
00538 if (namebuf == NULL || namebuf->length < 2)
00539 return(-1);
00540 d = ccn_buf_decoder_start(&decoder, namebuf->buf, namebuf->length);
00541 if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
00542 ccn_buf_advance(d);
00543 prev_ans = ans = d->decoder.token_index;
00544 while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00545 ccn_buf_advance(d);
00546 if (ccn_buf_match_blob(d, NULL, NULL)) {
00547 ccn_buf_advance(d);
00548 }
00549 ccn_buf_check_close(d);
00550 i += 1;
00551 if (prefix_comps < 0 || i <= prefix_comps) {
00552 prev_ans = ans;
00553 ans = d->decoder.token_index;
00554 }
00555 }
00556 ccn_buf_check_close(d);
00557 }
00558 if (d->decoder.state < 0 || ans < prefix_comps)
00559 return(-1);
00560 if (omit_possible_digest && ans == prev_ans + 36 && ans == namebuf->length - 1)
00561 return(prev_ans);
00562 return(ans);
00563 }
00564
00565 static void
00566 ccn_construct_interest(struct ccn *h,
00567 struct ccn_charbuf *name_prefix,
00568 struct ccn_charbuf *interest_template,
00569 struct expressed_interest *dest)
00570 {
00571 struct ccn_charbuf *c = h->interestbuf;
00572 size_t start;
00573 size_t size;
00574 int res;
00575
00576 dest->lifetime_us = CCN_INTEREST_LIFETIME_MICROSEC;
00577 c->length = 0;
00578 ccn_charbuf_append_tt(c, CCN_DTAG_Interest, CCN_DTAG);
00579 ccn_charbuf_append(c, name_prefix->buf, name_prefix->length);
00580 res = 0;
00581 if (interest_template != NULL) {
00582 struct ccn_parsed_interest pi = { 0 };
00583 res = ccn_parse_interest(interest_template->buf,
00584 interest_template->length, &pi, NULL);
00585 if (res >= 0) {
00586 intmax_t lifetime = ccn_interest_lifetime(interest_template->buf, &pi);
00587
00588 if (lifetime < 1 || lifetime > (30 << 12))
00589 NOTE_ERR(h, EINVAL);
00590 else
00591 dest->lifetime_us = (lifetime * 1000000) >> 12;
00592 start = pi.offset[CCN_PI_E_Name];
00593 size = pi.offset[CCN_PI_B_Nonce] - start;
00594 ccn_charbuf_append(c, interest_template->buf + start, size);
00595 start = pi.offset[CCN_PI_B_OTHER];
00596 size = pi.offset[CCN_PI_E_OTHER] - start;
00597 if (size != 0)
00598 ccn_charbuf_append(c, interest_template->buf + start, size);
00599 }
00600 else
00601 NOTE_ERR(h, EINVAL);
00602 }
00603 ccn_charbuf_append_closer(c);
00604 replace_interest_msg(dest, (res >= 0 ? c : NULL));
00605 }
00606
00607 int
00608 ccn_express_interest(struct ccn *h,
00609 struct ccn_charbuf *namebuf,
00610 struct ccn_closure *action,
00611 struct ccn_charbuf *interest_template)
00612 {
00613 struct hashtb_enumerator ee;
00614 struct hashtb_enumerator *e = ⅇ
00615 int res;
00616 int prefixend;
00617 struct expressed_interest *interest = NULL;
00618 struct interests_by_prefix *entry = NULL;
00619 if (h->interests_by_prefix == NULL) {
00620 h->interests_by_prefix = hashtb_create(sizeof(struct interests_by_prefix), NULL);
00621 if (h->interests_by_prefix == NULL)
00622 return(NOTE_ERRNO(h));
00623 }
00624 prefixend = ccn_check_namebuf(h, namebuf, -1, 1);
00625 if (prefixend < 0)
00626 return(prefixend);
00627
00628
00629
00630
00631 hashtb_start(h->interests_by_prefix, e);
00632 res = hashtb_seek(e, namebuf->buf + 1, prefixend - 1, 0);
00633 entry = e->data;
00634 if (entry == NULL) {
00635 NOTE_ERRNO(h);
00636 hashtb_end(e);
00637 return(res);
00638 }
00639 if (res == HT_NEW_ENTRY)
00640 entry->list = NULL;
00641 interest = calloc(1, sizeof(*interest));
00642 if (interest == NULL) {
00643 NOTE_ERRNO(h);
00644 hashtb_end(e);
00645 return(-1);
00646 }
00647 interest->magic = 0x7059e5f4;
00648 ccn_construct_interest(h, namebuf, interest_template, interest);
00649 if (interest->interest_msg == NULL) {
00650 free(interest);
00651 hashtb_end(e);
00652 return(-1);
00653 }
00654 ccn_replace_handler(h, &(interest->action), action);
00655 interest->target = 1;
00656 interest->next = entry->list;
00657 entry->list = interest;
00658 hashtb_end(e);
00659
00660 ccn_refresh_interest(h, interest);
00661 return(0);
00662 }
00663
00664 static void
00665 finalize_interest_filter(struct hashtb_enumerator *e)
00666 {
00667 struct interest_filter *i = e->data;
00668 if (i->ccn_reg_closure != NULL) {
00669 i->ccn_reg_closure->interest_filter = NULL;
00670 i->ccn_reg_closure = NULL;
00671 }
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 int
00693 ccn_set_interest_filter_with_flags(struct ccn *h, struct ccn_charbuf *namebuf,
00694 struct ccn_closure *action, int forw_flags)
00695 {
00696 struct hashtb_enumerator ee;
00697 struct hashtb_enumerator *e = ⅇ
00698 int res;
00699 struct interest_filter *entry;
00700
00701 if (h->interest_filters == NULL) {
00702 struct hashtb_param param = {0};
00703 param.finalize = &finalize_interest_filter;
00704 h->interest_filters = hashtb_create(sizeof(struct interest_filter), ¶m);
00705 if (h->interest_filters == NULL)
00706 return(NOTE_ERRNO(h));
00707 }
00708 res = ccn_check_namebuf(h, namebuf, -1, 0);
00709 if (res < 0)
00710 return(res);
00711 hashtb_start(h->interest_filters, e);
00712 res = hashtb_seek(e, namebuf->buf + 1, namebuf->length - 2, 0);
00713 if (res >= 0) {
00714 entry = e->data;
00715 if (entry->action != NULL && action != NULL && action != entry->action)
00716 res = update_multifilt(h, entry, action, forw_flags);
00717 else {
00718 update_ifilt_flags(h, entry, forw_flags);
00719 ccn_replace_handler(h, &(entry->action), action);
00720 }
00721 if (entry->action == NULL)
00722 hashtb_delete(e);
00723 }
00724 hashtb_end(e);
00725 return(res);
00726 }
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754 int
00755 ccn_set_interest_filter(struct ccn *h, struct ccn_charbuf *namebuf,
00756 struct ccn_closure *action)
00757 {
00758 int forw_flags = CCN_FORW_ACTIVE | CCN_FORW_CHILD_INHERIT;
00759 return(ccn_set_interest_filter_with_flags(h, namebuf, action, forw_flags));
00760 }
00761
00762
00763
00764
00765 static void
00766 update_ifilt_flags(struct ccn *h, struct interest_filter *f, int forw_flags)
00767 {
00768 if (f->flags != forw_flags) {
00769 memset(&f->expiry, 0, sizeof(f->expiry));
00770 f->flags = forw_flags;
00771 }
00772 }
00773
00774
00775
00776
00777
00778
00779 struct multifilt_item {
00780 struct ccn_closure *action;
00781 int forw_flags;
00782 };
00783
00784
00785
00786
00787
00788
00789
00790 struct multifilt {
00791 struct ccn_closure me;
00792 int n;
00793 struct multifilt_item *a;
00794 };
00795
00796
00797 static enum ccn_upcall_res handle_multifilt(struct ccn_closure *selfp,
00798 enum ccn_upcall_kind kind,
00799 struct ccn_upcall_info *info);
00800 static int build_multifilt_array(struct ccn *h,
00801 struct multifilt_item **ap,
00802 int n,
00803 struct ccn_closure *action,
00804 int forw_flags);
00805 static void destroy_multifilt_array(struct ccn *h,
00806 struct multifilt_item **ap,
00807 int n);
00808
00809
00810
00811
00812
00813
00814 static int
00815 update_multifilt(struct ccn *h,
00816 struct interest_filter *f,
00817 struct ccn_closure *action,
00818 int forw_flags)
00819 {
00820 struct multifilt *md = NULL;
00821 struct multifilt_item *a = NULL;
00822 int flags;
00823 int i;
00824 int n = 0;
00825
00826 if (action->p == &handle_multifilt) {
00827
00828 abort();
00829 }
00830 if (f->action->p == &handle_multifilt) {
00831
00832 md = f->action->data;
00833 if (md->me.data != md)
00834 abort();
00835 a = md->a;
00836 }
00837 else {
00838
00839 a = calloc(2, sizeof(*a));
00840 if (a == NULL)
00841 return(NOTE_ERRNO(h));
00842 md = calloc(1, sizeof(*md));
00843 if (md == NULL) {
00844 free(a);
00845 return(NOTE_ERRNO(h));
00846 }
00847 md->me.p = &handle_multifilt;
00848 md->me.data = md;
00849 md->n = 2;
00850 md->a = a;
00851 ccn_replace_handler(h, &(a[0].action), f->action);
00852 a[0].forw_flags = f->flags;
00853 ccn_replace_handler(h, &(a[1].action), action);
00854 a[1].forw_flags = 0;
00855 ccn_replace_handler(h, &f->action, &md->me);
00856 }
00857
00858 for (i = 0; i < n; i++) {
00859 if (a[i].action == action) {
00860 a[i].forw_flags = forw_flags;
00861 if (forw_flags == 0) {
00862 ccn_replace_handler(h, &(a[i].action), NULL);
00863 action = NULL;
00864 }
00865 goto Finish;
00866 }
00867 }
00868
00869 if (forw_flags == 0) {
00870 action->refcount++;
00871 ccn_replace_handler(h, &action, NULL);
00872 goto Finish;
00873 }
00874
00875 n = build_multifilt_array(h, &a, n, action, forw_flags);
00876 if (n < 0)
00877 return(n);
00878 destroy_multifilt_array(h, &md->a, md->n);
00879 md->a = a;
00880 md->n = n;
00881 Finish:
00882
00883 for (i = 0, flags = 0; i < n; i++)
00884 flags |= a[i].forw_flags;
00885 update_ifilt_flags(h, f, flags);
00886 return(0);
00887 }
00888
00889
00890
00891
00892
00893
00894
00895
00896 static int
00897 build_multifilt_array(struct ccn *h,
00898 struct multifilt_item **ap,
00899 int n,
00900 struct ccn_closure *action,
00901 int forw_flags)
00902 {
00903 struct multifilt_item *a = NULL;
00904 struct multifilt_item *c = NULL;
00905 int i, j, m;
00906
00907 a = *ap;
00908
00909 for (m = 0, i = 0; i < n; i++) {
00910 if (a[i].action != NULL)
00911 m++;
00912 }
00913 if (action != NULL)
00914 m++;
00915 if (m == 0) {
00916 *ap = NULL;
00917 return(0);
00918 }
00919 c = calloc(m, sizeof(*c));
00920 if (c == NULL)
00921 return(NOTE_ERRNO(h));
00922 for (i = 0, j = 0; i < n; i++) {
00923 if (a[i].action != NULL) {
00924 ccn_replace_handler(h, &(c[j].action), a[i].action);
00925 c[j].forw_flags = a[i].forw_flags;
00926 j++;
00927 }
00928 }
00929 if (j < m) {
00930 ccn_replace_handler(h, &(c[j].action), action);
00931 c[j].forw_flags = forw_flags;
00932 }
00933 *ap = c;
00934 return(m);
00935 }
00936
00937
00938
00939
00940 static void
00941 destroy_multifilt_array(struct ccn *h, struct multifilt_item **ap, int n)
00942 {
00943 struct multifilt_item *a;
00944 int i;
00945
00946 a = *ap;
00947 if (a != NULL) {
00948 for (i = 0; i < n; i++)
00949 ccn_replace_handler(h, &(a[i].action), NULL);
00950 free(a);
00951 *ap = NULL;
00952 }
00953 }
00954
00955
00956
00957
00958 static enum ccn_upcall_res
00959 handle_multifilt(struct ccn_closure *selfp,
00960 enum ccn_upcall_kind kind,
00961 struct ccn_upcall_info *info)
00962 {
00963 struct multifilt *md;
00964 struct multifilt_item *a;
00965 enum ccn_upcall_res ans;
00966 enum ccn_upcall_res res;
00967 int i, n;
00968
00969 md = selfp->data;
00970 if (kind == CCN_UPCALL_FINAL) {
00971 destroy_multifilt_array(info->h, &md->a, md->n);
00972 free(md);
00973 return(CCN_UPCALL_RESULT_OK);
00974 }
00975
00976
00977
00978
00979
00980 a = md->a;
00981 n = build_multifilt_array(info->h, &a, md->n, NULL, 0);
00982 ans = CCN_UPCALL_RESULT_OK;
00983 md = NULL;
00984 selfp = NULL;
00985 for (i = 0; i < n; i++) {
00986 if ((a[i].forw_flags & CCN_FORW_ACTIVE) != 0) {
00987 res = (a[i].action->p)(a[i].action, kind, info);
00988 if (res == CCN_UPCALL_RESULT_INTEREST_CONSUMED) {
00989 ans = res;
00990 if (kind == CCN_UPCALL_INTEREST)
00991 kind = CCN_UPCALL_CONSUMED_INTEREST;
00992 }
00993 }
00994 }
00995 destroy_multifilt_array(info->h, &a, n);
00996 return(ans);
00997 }
00998
00999
01000
01001 static int
01002 ccn_pushout(struct ccn *h)
01003 {
01004 ssize_t res;
01005 size_t size;
01006 if (h->outbuf != NULL && h->outbufindex < h->outbuf->length) {
01007 if (h->sock < 0)
01008 return(1);
01009 size = h->outbuf->length - h->outbufindex;
01010 res = write(h->sock, h->outbuf->buf + h->outbufindex, size);
01011 if (res == size) {
01012 h->outbuf->length = h->outbufindex = 0;
01013 return(0);
01014 }
01015 if (res == -1)
01016 return ((errno == EAGAIN) ? 1 : NOTE_ERRNO(h));
01017 h->outbufindex += res;
01018 return(1);
01019 }
01020 return(0);
01021 }
01022
01023 int
01024 ccn_put(struct ccn *h, const void *p, size_t length)
01025 {
01026 struct ccn_skeleton_decoder dd = {0};
01027 ssize_t res;
01028 if (h == NULL)
01029 return(-1);
01030 if (p == NULL || length == 0)
01031 return(NOTE_ERR(h, EINVAL));
01032 res = ccn_skeleton_decode(&dd, p, length);
01033 if (!(res == length && dd.state == 0))
01034 return(NOTE_ERR(h, EINVAL));
01035 if (h->tap != -1) {
01036 res = write(h->tap, p, length);
01037 if (res == -1) {
01038 NOTE_ERRNO(h);
01039 (void)close(h->tap);
01040 h->tap = -1;
01041 }
01042 }
01043 if (h->outbuf != NULL && h->outbufindex < h->outbuf->length) {
01044
01045 ccn_charbuf_append(h->outbuf, p, length);
01046 return (ccn_pushout(h));
01047 }
01048 if (h->sock == -1)
01049 res = 0;
01050 else
01051 res = write(h->sock, p, length);
01052 if (res == length)
01053 return(0);
01054 if (res == -1) {
01055 if (errno != EAGAIN)
01056 return(NOTE_ERRNO(h));
01057 res = 0;
01058 }
01059 if (h->outbuf == NULL) {
01060 h->outbuf = ccn_charbuf_create();
01061 h->outbufindex = 0;
01062 }
01063 ccn_charbuf_append(h->outbuf, ((const unsigned char *)p)+res, length-res);
01064 return(1);
01065 }
01066
01067 int
01068 ccn_output_is_pending(struct ccn *h)
01069 {
01070 return(h != NULL && h->outbuf != NULL && h->outbufindex < h->outbuf->length);
01071 }
01072
01073 struct ccn_charbuf *
01074 ccn_grab_buffered_output(struct ccn *h)
01075 {
01076 if (ccn_output_is_pending(h) && h->outbufindex == 0) {
01077 struct ccn_charbuf *ans = h->outbuf;
01078 h->outbuf = NULL;
01079 return(ans);
01080 }
01081 return(NULL);
01082 }
01083
01084 static void
01085 ccn_refresh_interest(struct ccn *h, struct expressed_interest *interest)
01086 {
01087 int res;
01088 if (interest->magic != 0x7059e5f4) {
01089 ccn_gripe(interest);
01090 return;
01091 }
01092 if (interest->outstanding < interest->target) {
01093 res = ccn_put(h, interest->interest_msg, interest->size);
01094 if (res >= 0) {
01095 interest->outstanding += 1;
01096 if (h->now.tv_sec == 0)
01097 gettimeofday(&h->now, NULL);
01098 interest->lasttime = h->now;
01099 }
01100 }
01101 }
01102
01103 static int
01104 ccn_get_content_type(const unsigned char *ccnb,
01105 const struct ccn_parsed_ContentObject *pco)
01106 {
01107 enum ccn_content_type type = pco->type;
01108 (void)ccnb;
01109 switch (type) {
01110 case CCN_CONTENT_DATA:
01111 case CCN_CONTENT_ENCR:
01112 case CCN_CONTENT_GONE:
01113 case CCN_CONTENT_KEY:
01114 case CCN_CONTENT_LINK:
01115 case CCN_CONTENT_NACK:
01116 return (type);
01117 default:
01118 return (-1);
01119 }
01120 }
01121
01122
01123
01124
01125 static void
01126 ccn_digest_Content(const unsigned char *content_object,
01127 struct ccn_parsed_ContentObject *pc,
01128 unsigned char *digest,
01129 size_t digest_bytes)
01130 {
01131 int res;
01132 struct ccn_digest *d = NULL;
01133 const unsigned char *content = NULL;
01134 size_t content_bytes = 0;
01135
01136 if (pc->magic < 20080000) abort();
01137 if (digest_bytes == sizeof(digest))
01138 return;
01139 d = ccn_digest_create(CCN_DIGEST_SHA256);
01140 ccn_digest_init(d);
01141 res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_object,
01142 pc->offset[CCN_PCO_B_Content],
01143 pc->offset[CCN_PCO_E_Content],
01144 &content, &content_bytes);
01145 if (res < 0) abort();
01146 res = ccn_digest_update(d, content, content_bytes);
01147 if (res < 0) abort();
01148 res = ccn_digest_final(d, digest, digest_bytes);
01149 if (res < 0) abort();
01150 ccn_digest_destroy(&d);
01151 }
01152
01153 static int
01154 ccn_cache_key(struct ccn *h,
01155 const unsigned char *ccnb, size_t size,
01156 struct ccn_parsed_ContentObject *pco)
01157 {
01158 int type;
01159 struct ccn_pkey **entry;
01160 struct hashtb_enumerator ee;
01161 struct hashtb_enumerator *e = ⅇ
01162 int res;
01163 unsigned char digest[32];
01164
01165 type = ccn_get_content_type(ccnb, pco);
01166 if (type != CCN_CONTENT_KEY) {
01167 return (0);
01168 }
01169
01170 ccn_digest_Content(ccnb, pco, digest, sizeof(digest));
01171
01172 hashtb_start(h->keys, e);
01173 res = hashtb_seek(e, (void *)digest, sizeof(digest), 0);
01174 if (res < 0) {
01175 hashtb_end(e);
01176 return(NOTE_ERRNO(h));
01177 }
01178 entry = e->data;
01179 if (res == HT_NEW_ENTRY) {
01180 struct ccn_pkey *pkey;
01181 const unsigned char *data = NULL;
01182 size_t data_size = 0;
01183
01184 res = ccn_content_get_value(ccnb, size, pco, &data, &data_size);
01185 if (res < 0) {
01186 hashtb_delete(e);
01187 hashtb_end(e);
01188 return(NOTE_ERRNO(h));
01189 }
01190 pkey = ccn_d2i_pubkey(data, data_size);
01191 if (pkey == NULL) {
01192 hashtb_delete(e);
01193 hashtb_end(e);
01194 return(NOTE_ERRNO(h));
01195 }
01196 *entry = pkey;
01197 }
01198 hashtb_end(e);
01199 return (0);
01200 }
01201
01202 static void
01203 finalize_pkey(struct hashtb_enumerator *e)
01204 {
01205 struct ccn_pkey **entry = e->data;
01206 if (*entry != NULL)
01207 ccn_pubkey_free(*entry);
01208 }
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220 static int
01221 ccn_locate_key(struct ccn *h,
01222 const unsigned char *msg,
01223 struct ccn_parsed_ContentObject *pco,
01224 struct ccn_pkey **pubkey)
01225 {
01226 int res;
01227 const unsigned char *pkeyid;
01228 size_t pkeyid_size;
01229 struct ccn_pkey **entry;
01230 struct ccn_buf_decoder decoder;
01231 struct ccn_buf_decoder *d;
01232
01233 if (h->keys == NULL) {
01234 return (NOTE_ERR(h, EINVAL));
01235 }
01236
01237 res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, msg,
01238 pco->offset[CCN_PCO_B_PublisherPublicKeyDigest],
01239 pco->offset[CCN_PCO_E_PublisherPublicKeyDigest],
01240 &pkeyid, &pkeyid_size);
01241 if (res < 0)
01242 return (NOTE_ERR(h, res));
01243 entry = hashtb_lookup(h->keys, pkeyid, pkeyid_size);
01244 if (entry != NULL) {
01245 *pubkey = *entry;
01246 return (0);
01247 }
01248
01249 if (pco->offset[CCN_PCO_B_KeyLocator] == pco->offset[CCN_PCO_E_KeyLocator])
01250 return (-1);
01251
01252 d = ccn_buf_decoder_start(&decoder, msg + pco->offset[CCN_PCO_B_Key_Certificate_KeyName],
01253 pco->offset[CCN_PCO_E_Key_Certificate_KeyName] -
01254 pco->offset[CCN_PCO_B_Key_Certificate_KeyName]);
01255 if (ccn_buf_match_dtag(d, CCN_DTAG_KeyName)) {
01256 return(1);
01257 }
01258 else if (ccn_buf_match_dtag(d, CCN_DTAG_Key)) {
01259 const unsigned char *dkey;
01260 size_t dkey_size;
01261 struct ccn_digest *digest = NULL;
01262 unsigned char *key_digest = NULL;
01263 size_t key_digest_size;
01264 struct hashtb_enumerator ee;
01265 struct hashtb_enumerator *e = ⅇ
01266
01267 res = ccn_ref_tagged_BLOB(CCN_DTAG_Key, msg,
01268 pco->offset[CCN_PCO_B_Key_Certificate_KeyName],
01269 pco->offset[CCN_PCO_E_Key_Certificate_KeyName],
01270 &dkey, &dkey_size);
01271 *pubkey = ccn_d2i_pubkey(dkey, dkey_size);
01272 digest = ccn_digest_create(CCN_DIGEST_SHA256);
01273 ccn_digest_init(digest);
01274 key_digest_size = ccn_digest_size(digest);
01275 key_digest = calloc(1, key_digest_size);
01276 if (key_digest == NULL) abort();
01277 res = ccn_digest_update(digest, dkey, dkey_size);
01278 if (res < 0) abort();
01279 res = ccn_digest_final(digest, key_digest, key_digest_size);
01280 if (res < 0) abort();
01281 ccn_digest_destroy(&digest);
01282 hashtb_start(h->keys, e);
01283 res = hashtb_seek(e, (void *)key_digest, key_digest_size, 0);
01284 free(key_digest);
01285 key_digest = NULL;
01286 if (res < 0) {
01287 hashtb_end(e);
01288 return(NOTE_ERRNO(h));
01289 }
01290 entry = e->data;
01291 if (res == HT_NEW_ENTRY) {
01292 *entry = *pubkey;
01293 }
01294 else
01295 THIS_CANNOT_HAPPEN(h);
01296 hashtb_end(e);
01297 return (0);
01298 }
01299 else if (ccn_buf_match_dtag(d, CCN_DTAG_Certificate)) {
01300 XXX;
01301 }
01302
01303 return (-1);
01304 }
01305
01306
01307
01308
01309
01310
01311 static int
01312 ccn_append_link_name(struct ccn_charbuf *name, const unsigned char *data, size_t data_size)
01313 {
01314 struct ccn_buf_decoder decoder;
01315 struct ccn_buf_decoder *d;
01316 size_t start = 0;
01317 size_t end = 0;
01318
01319 d = ccn_buf_decoder_start(&decoder, data, data_size);
01320 if (ccn_buf_match_dtag(d, CCN_DTAG_Link)) {
01321 ccn_buf_advance(d);
01322 start = d->decoder.token_index;
01323 ccn_parse_Name(d, NULL);
01324 end = d->decoder.token_index;
01325 ccn_buf_check_close(d);
01326 if (d->decoder.state < 0)
01327 return (d->decoder.state);
01328 ccn_charbuf_append(name, data + start, end - start);
01329 return(0);
01330 }
01331 return(-1);
01332 }
01333
01334
01335
01336
01337
01338
01339
01340 static enum ccn_upcall_res
01341 handle_key(struct ccn_closure *selfp,
01342 enum ccn_upcall_kind kind,
01343 struct ccn_upcall_info *info)
01344 {
01345 struct ccn *h = info->h;
01346 (void)h;
01347 int type = 0;
01348 const unsigned char *msg = NULL;
01349 const unsigned char *data = NULL;
01350 size_t size;
01351 size_t data_size;
01352 int res;
01353 struct ccn_charbuf *name = NULL;
01354 struct ccn_charbuf *templ = NULL;
01355
01356 switch(kind) {
01357 case CCN_UPCALL_FINAL:
01358 free(selfp);
01359 return(CCN_UPCALL_RESULT_OK);
01360 case CCN_UPCALL_INTEREST_TIMED_OUT:
01361
01362 return(CCN_UPCALL_RESULT_OK);
01363 case CCN_UPCALL_CONTENT_UNVERIFIED:
01364
01365 case CCN_UPCALL_CONTENT_KEYMISSING:
01366 case CCN_UPCALL_CONTENT_RAW:
01367 case CCN_UPCALL_CONTENT:
01368 type = ccn_get_content_type(msg, info->pco);
01369 if (type == CCN_CONTENT_KEY)
01370 return(CCN_UPCALL_RESULT_OK);
01371 if (type == CCN_CONTENT_LINK) {
01372
01373
01374 if (selfp->intdata <= 0)
01375 return(NOTE_ERR(h, ELOOP));
01376 selfp->intdata -= 1;
01377 msg = info->content_ccnb;
01378 size = info->pco->offset[CCN_PCO_E];
01379 res = ccn_content_get_value(info->content_ccnb, size, info->pco,
01380 &data, &data_size);
01381 if (res < 0)
01382 return (CCN_UPCALL_RESULT_ERR);
01383 templ = ccn_charbuf_create();
01384 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
01385 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
01386 ccn_charbuf_append_closer(templ);
01387 ccnb_tagged_putf(templ, CCN_DTAG_MinSuffixComponents, "%d", 1);
01388 ccnb_tagged_putf(templ, CCN_DTAG_MaxSuffixComponents, "%d", 3);
01389 ccn_charbuf_append_closer(templ);
01390 name = ccn_charbuf_create();
01391 res = ccn_append_link_name(name, data, data_size);
01392 if (res < 0) {
01393 NOTE_ERR(h, EINVAL);
01394 res = CCN_UPCALL_RESULT_ERR;
01395 }
01396 else
01397 res = ccn_express_interest(h, name, selfp, templ);
01398 ccn_charbuf_destroy(&name);
01399 ccn_charbuf_destroy(&templ);
01400 return(res);
01401 }
01402 return (CCN_UPCALL_RESULT_ERR);
01403 default:
01404 return (CCN_UPCALL_RESULT_ERR);
01405 }
01406 }
01407
01408
01409
01410
01411
01412 #ifndef CCN_MAX_KEY_LINK_CHAIN
01413 #define CCN_MAX_KEY_LINK_CHAIN 7
01414 #endif
01415
01416 static int
01417 ccn_initiate_key_fetch(struct ccn *h,
01418 unsigned char *msg,
01419 struct ccn_parsed_ContentObject *pco,
01420 struct expressed_interest *trigger_interest)
01421 {
01422
01423
01424
01425
01426
01427 int res;
01428 int namelen;
01429 struct ccn_charbuf *key_name = NULL;
01430 struct ccn_closure *key_closure = NULL;
01431 const unsigned char *pkeyid = NULL;
01432 size_t pkeyid_size = 0;
01433 struct ccn_charbuf *templ = NULL;
01434
01435 if (trigger_interest != NULL) {
01436
01437 if (trigger_interest->wanted_pub == NULL)
01438 trigger_interest->wanted_pub = ccn_charbuf_create();
01439 res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, msg,
01440 pco->offset[CCN_PCO_B_PublisherPublicKeyDigest],
01441 pco->offset[CCN_PCO_E_PublisherPublicKeyDigest],
01442 &pkeyid, &pkeyid_size);
01443 if (trigger_interest->wanted_pub != NULL && res >= 0) {
01444 trigger_interest->wanted_pub->length = 0;
01445 ccn_charbuf_append(trigger_interest->wanted_pub, pkeyid, pkeyid_size);
01446 }
01447 trigger_interest->target = 0;
01448 }
01449
01450 namelen = (pco->offset[CCN_PCO_E_KeyName_Name] -
01451 pco->offset[CCN_PCO_B_KeyName_Name]);
01452
01453
01454
01455
01456 if (namelen == 0)
01457 return(-1);
01458 key_closure = calloc(1, sizeof(*key_closure));
01459 if (key_closure == NULL)
01460 return (NOTE_ERRNO(h));
01461 key_closure->p = &handle_key;
01462 key_closure->intdata = CCN_MAX_KEY_LINK_CHAIN;
01463
01464 key_name = ccn_charbuf_create();
01465 res = ccn_charbuf_append(key_name,
01466 msg + pco->offset[CCN_PCO_B_KeyName_Name],
01467 namelen);
01468 templ = ccn_charbuf_create();
01469 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
01470 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
01471 ccn_charbuf_append_closer(templ);
01472 ccnb_tagged_putf(templ, CCN_DTAG_MinSuffixComponents, "%d", 1);
01473 ccnb_tagged_putf(templ, CCN_DTAG_MaxSuffixComponents, "%d", 3);
01474 if (pco->offset[CCN_PCO_B_KeyName_Pub] < pco->offset[CCN_PCO_E_KeyName_Pub]) {
01475 ccn_charbuf_append(templ,
01476 msg + pco->offset[CCN_PCO_B_KeyName_Pub],
01477 (pco->offset[CCN_PCO_E_KeyName_Pub] -
01478 pco->offset[CCN_PCO_B_KeyName_Pub]));
01479 }
01480 ccn_charbuf_append_closer(templ);
01481 res = ccn_express_interest(h, key_name, key_closure, templ);
01482 ccn_charbuf_destroy(&key_name);
01483 ccn_charbuf_destroy(&templ);
01484 return(res);
01485 }
01486
01487
01488
01489
01490
01491 static void
01492 ccn_check_pub_arrival(struct ccn *h, struct expressed_interest *interest)
01493 {
01494 struct ccn_charbuf *want = interest->wanted_pub;
01495 if (want == NULL)
01496 return;
01497 if (hashtb_lookup(h->keys, want->buf, want->length) != NULL) {
01498 ccn_charbuf_destroy(&interest->wanted_pub);
01499 interest->target = 1;
01500 ccn_refresh_interest(h, interest);
01501 }
01502 }
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512 void
01513 ccn_dispatch_message(struct ccn *h, unsigned char *msg, size_t size)
01514 {
01515 struct ccn_parsed_interest pi = {0};
01516 struct ccn_upcall_info info = {0};
01517 int i;
01518 int res;
01519 enum ccn_upcall_res ures;
01520
01521 h->running++;
01522 info.h = h;
01523 info.pi = π
01524 info.interest_comps = ccn_indexbuf_obtain(h);
01525 res = ccn_parse_interest(msg, size, &pi, info.interest_comps);
01526 if (res >= 0) {
01527
01528 enum ccn_upcall_kind upcall_kind = CCN_UPCALL_INTEREST;
01529 info.interest_ccnb = msg;
01530 if (h->interest_filters != NULL && info.interest_comps->n > 0) {
01531 struct ccn_indexbuf *comps = info.interest_comps;
01532 size_t keystart = comps->buf[0];
01533 unsigned char *key = msg + keystart;
01534 struct interest_filter *entry;
01535 for (i = comps->n - 1; i >= 0; i--) {
01536 entry = hashtb_lookup(h->interest_filters, key, comps->buf[i] - keystart);
01537 if (entry != NULL) {
01538 info.matched_comps = i;
01539 ures = (entry->action->p)(entry->action, upcall_kind, &info);
01540 if (ures == CCN_UPCALL_RESULT_INTEREST_CONSUMED)
01541 upcall_kind = CCN_UPCALL_CONSUMED_INTEREST;
01542 }
01543 }
01544 }
01545 }
01546 else {
01547
01548 struct ccn_parsed_ContentObject obj = {0};
01549 info.pco = &obj;
01550 info.content_comps = ccn_indexbuf_create();
01551 res = ccn_parse_ContentObject(msg, size, &obj, info.content_comps);
01552 if (res >= 0) {
01553 info.content_ccnb = msg;
01554 if (h->interests_by_prefix != NULL) {
01555 struct ccn_indexbuf *comps = info.content_comps;
01556 size_t keystart = comps->buf[0];
01557 unsigned char *key = msg + keystart;
01558 struct expressed_interest *interest = NULL;
01559 struct interests_by_prefix *entry = NULL;
01560 for (i = comps->n - 1; i >= 0; i--) {
01561 entry = hashtb_lookup(h->interests_by_prefix, key, comps->buf[i] - keystart);
01562 if (entry != NULL) {
01563 for (interest = entry->list; interest != NULL; interest = interest->next) {
01564 if (interest->magic != 0x7059e5f4) {
01565 ccn_gripe(interest);
01566 }
01567 if (interest->target > 0 && interest->outstanding > 0) {
01568 res = ccn_parse_interest(interest->interest_msg,
01569 interest->size,
01570 info.pi,
01571 info.interest_comps);
01572 if (res >= 0 &&
01573 ccn_content_matches_interest(msg, size,
01574 1, info.pco,
01575 interest->interest_msg,
01576 interest->size,
01577 info.pi)) {
01578 enum ccn_upcall_kind upcall_kind = CCN_UPCALL_CONTENT;
01579 struct ccn_pkey *pubkey = NULL;
01580 int type = ccn_get_content_type(msg, info.pco);
01581 if (type == CCN_CONTENT_KEY)
01582 res = ccn_cache_key(h, msg, size, info.pco);
01583 res = ccn_locate_key(h, msg, info.pco, &pubkey);
01584 if (h->defer_verification) {
01585 if (res == 0)
01586 upcall_kind = CCN_UPCALL_CONTENT_RAW;
01587 else
01588 upcall_kind = CCN_UPCALL_CONTENT_KEYMISSING;
01589 }
01590 else if (res == 0) {
01591
01592 res = ccn_verify_signature(msg, size, info.pco, pubkey);
01593 upcall_kind = (res == 1) ? CCN_UPCALL_CONTENT : CCN_UPCALL_CONTENT_BAD;
01594 } else
01595 upcall_kind = CCN_UPCALL_CONTENT_UNVERIFIED;
01596 interest->outstanding -= 1;
01597 info.interest_ccnb = interest->interest_msg;
01598 info.matched_comps = i;
01599 ures = (interest->action->p)(interest->action,
01600 upcall_kind,
01601 &info);
01602 if (interest->magic != 0x7059e5f4)
01603 ccn_gripe(interest);
01604 if (ures == CCN_UPCALL_RESULT_REEXPRESS)
01605 ccn_refresh_interest(h, interest);
01606 else if ((ures == CCN_UPCALL_RESULT_VERIFY ||
01607 ures == CCN_UPCALL_RESULT_FETCHKEY) &&
01608 (upcall_kind == CCN_UPCALL_CONTENT_UNVERIFIED ||
01609 upcall_kind == CCN_UPCALL_CONTENT_KEYMISSING)) {
01610 ccn_initiate_key_fetch(h, msg, info.pco, interest);
01611 }
01612 else if (ures == CCN_UPCALL_RESULT_VERIFY &&
01613 upcall_kind == CCN_UPCALL_CONTENT_RAW) {
01614
01615 abort();
01616 }
01617 else {
01618 interest->target = 0;
01619 replace_interest_msg(interest, NULL);
01620 ccn_replace_handler(h, &(interest->action), NULL);
01621 }
01622 }
01623 }
01624 }
01625 }
01626 }
01627 }
01628 }
01629 }
01630 ccn_indexbuf_release(h, info.interest_comps);
01631 ccn_indexbuf_destroy(&info.content_comps);
01632 h->running--;
01633 }
01634
01635 static int
01636 ccn_process_input(struct ccn *h)
01637 {
01638 ssize_t res;
01639 ssize_t msgstart;
01640 unsigned char *buf;
01641 struct ccn_skeleton_decoder *d = &h->decoder;
01642 struct ccn_charbuf *inbuf = h->inbuf;
01643 if (inbuf == NULL)
01644 h->inbuf = inbuf = ccn_charbuf_create();
01645 if (inbuf->length == 0)
01646 memset(d, 0, sizeof(*d));
01647 buf = ccn_charbuf_reserve(inbuf, 8800);
01648 res = read(h->sock, buf, inbuf->limit - inbuf->length);
01649 if (res == 0) {
01650 ccn_disconnect(h);
01651 return(-1);
01652 }
01653 if (res == -1) {
01654 if (errno == EAGAIN)
01655 res = 0;
01656 else
01657 return(NOTE_ERRNO(h));
01658 }
01659 inbuf->length += res;
01660 msgstart = 0;
01661 ccn_skeleton_decode(d, buf, res);
01662 while (d->state == 0) {
01663 ccn_dispatch_message(h, inbuf->buf + msgstart,
01664 d->index - msgstart);
01665 msgstart = d->index;
01666 if (msgstart == inbuf->length) {
01667 inbuf->length = 0;
01668 return(0);
01669 }
01670 ccn_skeleton_decode(d, inbuf->buf + d->index,
01671 inbuf->length - d->index);
01672 }
01673 if (msgstart < inbuf->length && msgstart > 0) {
01674
01675 memmove(inbuf->buf, inbuf->buf + msgstart,
01676 inbuf->length - msgstart);
01677 inbuf->length -= msgstart;
01678 d->index -= msgstart;
01679 }
01680 return(0);
01681 }
01682
01683 static void
01684 ccn_update_refresh_us(struct ccn *h, struct timeval *tv)
01685 {
01686 int delta;
01687 if (tv->tv_sec < h->now.tv_sec)
01688 return;
01689 if (tv->tv_sec > h->now.tv_sec + CCN_INTEREST_LIFETIME_SEC)
01690 return;
01691 delta = (tv->tv_sec - h->now.tv_sec)*1000000 +
01692 (tv->tv_usec - h->now.tv_usec);
01693 if (delta < 0)
01694 delta = 0;
01695 if (delta < h->refresh_us)
01696 h->refresh_us = delta;
01697 }
01698
01699 static void
01700 ccn_age_interest(struct ccn *h,
01701 struct expressed_interest *interest,
01702 const unsigned char *key, size_t keysize)
01703 {
01704 struct ccn_parsed_interest pi = {0};
01705 struct ccn_upcall_info info = {0};
01706 int delta;
01707 int res;
01708 enum ccn_upcall_res ures;
01709 int firstcall;
01710 if (interest->magic != 0x7059e5f4)
01711 ccn_gripe(interest);
01712 info.h = h;
01713 info.pi = π
01714 firstcall = (interest->lasttime.tv_sec == 0);
01715 if (interest->lasttime.tv_sec + 30 < h->now.tv_sec) {
01716
01717 interest->outstanding = 0;
01718 interest->lasttime = h->now;
01719 interest->lasttime.tv_sec -= 30;
01720 }
01721 delta = (h->now.tv_sec - interest->lasttime.tv_sec)*1000000 +
01722 (h->now.tv_usec - interest->lasttime.tv_usec);
01723 if (delta >= interest->lifetime_us) {
01724 interest->outstanding = 0;
01725 delta = 0;
01726 }
01727 else if (delta < 0)
01728 delta = 0;
01729 if (interest->lifetime_us - delta < h->refresh_us)
01730 h->refresh_us = interest->lifetime_us - delta;
01731 interest->lasttime = h->now;
01732 while (delta > interest->lasttime.tv_usec) {
01733 delta -= 1000000;
01734 interest->lasttime.tv_sec -= 1;
01735 }
01736 interest->lasttime.tv_usec -= delta;
01737 if (interest->target > 0 && interest->outstanding == 0) {
01738 ures = CCN_UPCALL_RESULT_REEXPRESS;
01739 if (!firstcall) {
01740 info.interest_ccnb = interest->interest_msg;
01741 info.interest_comps = ccn_indexbuf_obtain(h);
01742 res = ccn_parse_interest(interest->interest_msg,
01743 interest->size,
01744 info.pi,
01745 info.interest_comps);
01746 if (res >= 0) {
01747 ures = (interest->action->p)(interest->action,
01748 CCN_UPCALL_INTEREST_TIMED_OUT,
01749 &info);
01750 if (interest->magic != 0x7059e5f4)
01751 ccn_gripe(interest);
01752 }
01753 else {
01754 int i;
01755 fprintf(stderr, "URP!! interest has been corrupted ccn_client.c:%d\n", __LINE__);
01756 for (i = 0; i < 120; i++)
01757 sleep(1);
01758 ures = CCN_UPCALL_RESULT_ERR;
01759 }
01760 ccn_indexbuf_release(h, info.interest_comps);
01761 }
01762 if (ures == CCN_UPCALL_RESULT_REEXPRESS)
01763 ccn_refresh_interest(h, interest);
01764 else
01765 interest->target = 0;
01766 }
01767 }
01768
01769 static void
01770 ccn_clean_all_interests(struct ccn *h)
01771 {
01772 struct hashtb_enumerator ee;
01773 struct hashtb_enumerator *e = ⅇ
01774 struct interests_by_prefix *entry;
01775 for (hashtb_start(h->interests_by_prefix, e); e->data != NULL;) {
01776 entry = e->data;
01777 ccn_clean_interests_by_prefix(h, entry);
01778 if (entry->list == NULL)
01779 hashtb_delete(e);
01780 else
01781 hashtb_next(e);
01782 }
01783 hashtb_end(e);
01784 }
01785
01786 static void
01787 ccn_notify_ccndid_changed(struct ccn *h)
01788 {
01789 struct hashtb_enumerator ee;
01790 struct hashtb_enumerator *e = ⅇ
01791 if (h->interest_filters != NULL) {
01792 for (hashtb_start(h->interest_filters, e); e->data != NULL; hashtb_next(e)) {
01793 struct interest_filter *i = e->data;
01794 if ((i->flags & CCN_FORW_WAITING_CCNDID) != 0) {
01795 i->expiry = h->now;
01796 i->flags &= ~CCN_FORW_WAITING_CCNDID;
01797 }
01798 }
01799 hashtb_end(e);
01800 }
01801 }
01802
01803
01804
01805
01806
01807
01808 struct ccn_schedule *
01809 ccn_get_schedule(struct ccn *h)
01810 {
01811 return(h->schedule);
01812 }
01813
01814
01815
01816
01817
01818
01819
01820 struct ccn_schedule *
01821 ccn_set_schedule(struct ccn *h, struct ccn_schedule *schedule)
01822 {
01823 struct ccn_schedule *old = h->schedule;
01824 h->schedule = schedule;
01825 return(old);
01826 }
01827
01828
01829
01830
01831
01832
01833
01834
01835 int
01836 ccn_process_scheduled_operations(struct ccn *h)
01837 {
01838 struct hashtb_enumerator ee;
01839 struct hashtb_enumerator *e = ⅇ
01840 struct interests_by_prefix *entry;
01841 struct expressed_interest *ie;
01842 int need_clean = 0;
01843 h->refresh_us = 5 * CCN_INTEREST_LIFETIME_MICROSEC;
01844 gettimeofday(&h->now, NULL);
01845 if (ccn_output_is_pending(h))
01846 return(h->refresh_us);
01847 h->running++;
01848 if (h->interest_filters != NULL) {
01849 for (hashtb_start(h->interest_filters, e); e->data != NULL; hashtb_next(e)) {
01850 struct interest_filter *i = e->data;
01851 if (tv_earlier(&i->expiry, &h->now)) {
01852
01853 ccn_initiate_prefix_reg(h, e->key, e->keysize, i);
01854 }
01855 else
01856 ccn_update_refresh_us(h, &i->expiry);
01857 }
01858 hashtb_end(e);
01859 }
01860 if (h->interests_by_prefix != NULL) {
01861 for (hashtb_start(h->interests_by_prefix, e); e->data != NULL; hashtb_next(e)) {
01862 entry = e->data;
01863 ccn_check_interests(entry->list);
01864 if (entry->list == NULL)
01865 need_clean = 1;
01866 else {
01867 for (ie = entry->list; ie != NULL; ie = ie->next) {
01868 ccn_check_pub_arrival(h, ie);
01869 if (ie->target != 0)
01870 ccn_age_interest(h, ie, e->key, e->keysize);
01871 if (ie->target == 0 && ie->wanted_pub == NULL) {
01872 ccn_replace_handler(h, &(ie->action), NULL);
01873 replace_interest_msg(ie, NULL);
01874 need_clean = 1;
01875 }
01876 }
01877 }
01878 }
01879 hashtb_end(e);
01880 if (need_clean)
01881 ccn_clean_all_interests(h);
01882 }
01883 h->running--;
01884 return(h->refresh_us);
01885 }
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897 int
01898 ccn_set_run_timeout(struct ccn *h, int timeout)
01899 {
01900 int ans = h->timeout;
01901 h->timeout = timeout;
01902 return(ans);
01903 }
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913 int
01914 ccn_run(struct ccn *h, int timeout)
01915 {
01916 struct timeval start;
01917 struct pollfd fds[1];
01918 int microsec;
01919 int s_microsec = -1;
01920 int millisec;
01921 int res = -1;
01922 if (h->running != 0)
01923 return(NOTE_ERR(h, EBUSY));
01924 memset(fds, 0, sizeof(fds));
01925 memset(&start, 0, sizeof(start));
01926 h->timeout = timeout;
01927 for (;;) {
01928 if (h->sock == -1) {
01929 res = -1;
01930 break;
01931 }
01932 if (h->schedule != NULL) {
01933 s_microsec = ccn_schedule_run(h->schedule);
01934 }
01935 microsec = ccn_process_scheduled_operations(h);
01936 if (s_microsec >= 0 && s_microsec < microsec)
01937 microsec = s_microsec;
01938 timeout = h->timeout;
01939 if (start.tv_sec == 0)
01940 start = h->now;
01941 else if (timeout >= 0) {
01942 millisec = (h->now.tv_sec - start.tv_sec) *1000 +
01943 (h->now.tv_usec - start.tv_usec)/1000;
01944 if (millisec >= timeout) {
01945 res = 0;
01946 break;
01947 }
01948 }
01949 fds[0].fd = h->sock;
01950 fds[0].events = POLLIN;
01951 if (ccn_output_is_pending(h))
01952 fds[0].events |= POLLOUT;
01953 millisec = microsec / 1000;
01954 if (timeout >= 0 && timeout < millisec)
01955 millisec = timeout;
01956 res = poll(fds, 1, millisec);
01957 if (res < 0 && errno != EINTR) {
01958 res = NOTE_ERRNO(h);
01959 break;
01960 }
01961 if (res > 0) {
01962 if ((fds[0].revents | POLLOUT) != 0)
01963 ccn_pushout(h);
01964 if ((fds[0].revents | POLLIN) != 0)
01965 ccn_process_input(h);
01966 }
01967 if (h->err == ENOTCONN)
01968 ccn_disconnect(h);
01969 if (h->timeout == 0)
01970 break;
01971 }
01972 if (h->running != 0)
01973 abort();
01974 return((res < 0) ? res : 0);
01975 }
01976
01977
01978
01979
01980 struct simple_get_data {
01981 struct ccn_closure closure;
01982 struct ccn_charbuf *resultbuf;
01983 struct ccn_parsed_ContentObject *pcobuf;
01984 struct ccn_indexbuf *compsbuf;
01985 int flags;
01986 int res;
01987 };
01988
01989
01990
01991
01992 static enum ccn_upcall_res
01993 handle_simple_incoming_content(
01994 struct ccn_closure *selfp,
01995 enum ccn_upcall_kind kind,
01996 struct ccn_upcall_info *info)
01997 {
01998 struct simple_get_data *md = selfp->data;
01999 struct ccn *h = info->h;
02000
02001 if (kind == CCN_UPCALL_FINAL) {
02002 if (selfp != &md->closure)
02003 abort();
02004 free(md);
02005 return(CCN_UPCALL_RESULT_OK);
02006 }
02007 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
02008 return(selfp->intdata ? CCN_UPCALL_RESULT_REEXPRESS : CCN_UPCALL_RESULT_OK);
02009 if (kind == CCN_UPCALL_CONTENT_UNVERIFIED) {
02010 if ((md->flags & CCN_GET_NOKEYWAIT) == 0)
02011 return(CCN_UPCALL_RESULT_VERIFY);
02012 }
02013 if (kind == CCN_UPCALL_CONTENT_KEYMISSING) {
02014 if ((md->flags & CCN_GET_NOKEYWAIT) == 0)
02015 return(CCN_UPCALL_RESULT_FETCHKEY);
02016 }
02017 else if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_RAW)
02018 return(CCN_UPCALL_RESULT_ERR);
02019 if (md->resultbuf != NULL) {
02020 md->resultbuf->length = 0;
02021 ccn_charbuf_append(md->resultbuf,
02022 info->content_ccnb, info->pco->offset[CCN_PCO_E]);
02023 }
02024 if (md->pcobuf != NULL)
02025 memcpy(md->pcobuf, info->pco, sizeof(*md->pcobuf));
02026 if (md->compsbuf != NULL) {
02027 md->compsbuf->n = 0;
02028 ccn_indexbuf_append(md->compsbuf,
02029 info->content_comps->buf, info->content_comps->n);
02030 }
02031 md->res = 0;
02032 ccn_set_run_timeout(h, 0);
02033 return(CCN_UPCALL_RESULT_OK);
02034 }
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055 int
02056 ccn_get(struct ccn *h,
02057 struct ccn_charbuf *name,
02058 struct ccn_charbuf *interest_template,
02059 int timeout_ms,
02060 struct ccn_charbuf *resultbuf,
02061 struct ccn_parsed_ContentObject *pcobuf,
02062 struct ccn_indexbuf *compsbuf,
02063 int flags)
02064 {
02065 struct ccn *orig_h = h;
02066 struct hashtb *saved_keys = NULL;
02067 int res;
02068 struct simple_get_data *md;
02069
02070 if ((flags & ~((int)CCN_GET_NOKEYWAIT)) != 0)
02071 return(-1);
02072 if (h == NULL || h->running) {
02073 h = ccn_create();
02074 if (h == NULL)
02075 return(-1);
02076 if (orig_h != NULL) {
02077 saved_keys = h->keys;
02078 h->keys = orig_h->keys;
02079 }
02080 res = ccn_connect(h, NULL);
02081 if (res < 0) {
02082 ccn_destroy(&h);
02083 return(-1);
02084 }
02085 }
02086 md = calloc(1, sizeof(*md));
02087 md->resultbuf = resultbuf;
02088 md->pcobuf = pcobuf;
02089 md->compsbuf = compsbuf;
02090 md->flags = flags;
02091 md->res = -1;
02092 md->closure.p = &handle_simple_incoming_content;
02093 md->closure.data = md;
02094 md->closure.intdata = 1;
02095 md->closure.refcount = 1;
02096 res = ccn_express_interest(h, name, &md->closure, interest_template);
02097 if (res >= 0)
02098 res = ccn_run(h, timeout_ms);
02099 if (res >= 0)
02100 res = md->res;
02101 md->resultbuf = NULL;
02102 md->pcobuf = NULL;
02103 md->compsbuf = NULL;
02104 md->closure.intdata = 0;
02105 md->closure.refcount--;
02106 if (md->closure.refcount == 0)
02107 free(md);
02108 if (h != orig_h) {
02109 if (saved_keys != NULL)
02110 h->keys = saved_keys;
02111 ccn_destroy(&h);
02112 }
02113 return(res);
02114 }
02115
02116
02117
02118
02119 static enum ccn_upcall_res
02120 handle_ccndid_response(struct ccn_closure *selfp,
02121 enum ccn_upcall_kind kind,
02122 struct ccn_upcall_info *info)
02123 {
02124 int res;
02125 const unsigned char *ccndid = NULL;
02126 size_t size = 0;
02127 struct ccn *h = info->h;
02128
02129 if (kind == CCN_UPCALL_FINAL) {
02130 free(selfp);
02131 return(CCN_UPCALL_RESULT_OK);
02132 }
02133 if (kind == CCN_UPCALL_CONTENT_UNVERIFIED)
02134 return(CCN_UPCALL_RESULT_VERIFY);
02135 if (kind == CCN_UPCALL_CONTENT_KEYMISSING)
02136 return(CCN_UPCALL_RESULT_FETCHKEY);
02137 if (kind == CCN_UPCALL_CONTENT_RAW) {
02138 if (ccn_verify_content(h, info->content_ccnb, info->pco) == 0)
02139 kind = CCN_UPCALL_CONTENT;
02140 }
02141 if (kind != CCN_UPCALL_CONTENT) {
02142 NOTE_ERR(h, -1000 - kind);
02143 return(CCN_UPCALL_RESULT_ERR);
02144 }
02145 res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest,
02146 info->content_ccnb,
02147 info->pco->offset[CCN_PCO_B_PublisherPublicKeyDigest],
02148 info->pco->offset[CCN_PCO_E_PublisherPublicKeyDigest],
02149 &ccndid,
02150 &size);
02151 if (res < 0) {
02152 NOTE_ERR(h, -1);
02153 return(CCN_UPCALL_RESULT_ERR);
02154 }
02155 if (h->ccndid == NULL) {
02156 h->ccndid = ccn_charbuf_create_n(size);
02157 if (h->ccndid == NULL)
02158 return(NOTE_ERRNO(h));
02159 }
02160 ccn_charbuf_reset(h->ccndid);
02161 ccn_charbuf_append(h->ccndid, ccndid, size);
02162 ccn_notify_ccndid_changed(h);
02163 return(CCN_UPCALL_RESULT_OK);
02164 }
02165
02166 static void
02167 ccn_initiate_ccndid_fetch(struct ccn *h)
02168 {
02169 struct ccn_charbuf *name = NULL;
02170 struct ccn_closure *action = NULL;
02171
02172 name = ccn_charbuf_create();
02173 ccn_name_from_uri(name, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY");
02174 action = calloc(1, sizeof(*action));
02175 action->p = &handle_ccndid_response;
02176 ccn_express_interest(h, name, action, NULL);
02177 ccn_charbuf_destroy(&name);
02178 }
02179
02180
02181
02182
02183 static enum ccn_upcall_res
02184 handle_prefix_reg_reply(
02185 struct ccn_closure *selfp,
02186 enum ccn_upcall_kind kind,
02187 struct ccn_upcall_info *info)
02188 {
02189 struct ccn_reg_closure *md = selfp->data;
02190 struct ccn *h = info->h;
02191 int lifetime = 10;
02192 struct ccn_forwarding_entry *fe = NULL;
02193 int res;
02194 const unsigned char *fe_ccnb = NULL;
02195 size_t fe_ccnb_size = 0;
02196
02197 if (kind == CCN_UPCALL_FINAL) {
02198
02199 if (selfp != &md->action)
02200 abort();
02201 if (md->interest_filter != NULL)
02202 md->interest_filter->ccn_reg_closure = NULL;
02203 selfp->data = NULL;
02204 free(md);
02205 return(CCN_UPCALL_RESULT_OK);
02206 }
02207 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
02208 return(CCN_UPCALL_RESULT_REEXPRESS);
02209 if (kind == CCN_UPCALL_CONTENT_UNVERIFIED)
02210 return(CCN_UPCALL_RESULT_VERIFY);
02211 if (kind == CCN_UPCALL_CONTENT_KEYMISSING)
02212 return(CCN_UPCALL_RESULT_FETCHKEY);
02213 if (kind == CCN_UPCALL_CONTENT_RAW) {
02214 if (ccn_verify_content(h, info->content_ccnb, info->pco) == 0)
02215 kind = CCN_UPCALL_CONTENT;
02216 }
02217 if (kind != CCN_UPCALL_CONTENT) {
02218 NOTE_ERR(h, -1000 - kind);
02219 return(CCN_UPCALL_RESULT_ERR);
02220 }
02221 res = ccn_content_get_value(info->content_ccnb,
02222 info->pco->offset[CCN_PCO_E],
02223 info->pco,
02224 &fe_ccnb, &fe_ccnb_size);
02225 if (res == 0)
02226 fe = ccn_forwarding_entry_parse(fe_ccnb, fe_ccnb_size);
02227 if (fe == NULL) {
02228 XXX;
02229 lifetime = 30;
02230 }
02231 else
02232 lifetime = fe->lifetime;
02233 if (lifetime < 0)
02234 lifetime = 0;
02235 else if (lifetime > 3600)
02236 lifetime = 3600;
02237 if (md->interest_filter != NULL) {
02238 md->interest_filter->expiry = h->now;
02239 md->interest_filter->expiry.tv_sec += lifetime;
02240 }
02241 ccn_forwarding_entry_destroy(&fe);
02242 return(CCN_UPCALL_RESULT_OK);
02243 }
02244
02245 static void
02246 ccn_initiate_prefix_reg(struct ccn *h,
02247 const void *prefix, size_t prefix_size,
02248 struct interest_filter *i)
02249 {
02250 struct ccn_reg_closure *p = NULL;
02251 struct ccn_charbuf *reqname = NULL;
02252 struct ccn_charbuf *templ = NULL;
02253 struct ccn_forwarding_entry fe_store = { 0 };
02254 struct ccn_forwarding_entry *fe = &fe_store;
02255 struct ccn_charbuf *reg_request = NULL;
02256 struct ccn_charbuf *signed_reg_request = NULL;
02257 struct ccn_charbuf *empty = NULL;
02258
02259 i->expiry = h->now;
02260 i->expiry.tv_sec += 60;
02261
02262 if (h->sock == -1)
02263 return;
02264
02265 if (h->ccndid == NULL) {
02266 ccn_initiate_ccndid_fetch(h);
02267 i->flags |= CCN_FORW_WAITING_CCNDID;
02268 return;
02269 }
02270 if (i->ccn_reg_closure != NULL)
02271 return;
02272 p = calloc(1, sizeof(*p));
02273 if (p == NULL) {
02274 NOTE_ERRNO(h);
02275 return;
02276 }
02277 p->action.data = p;
02278 p->action.p = &handle_prefix_reg_reply;
02279 p->interest_filter = i;
02280 i->ccn_reg_closure = p;
02281 reqname = ccn_charbuf_create();
02282 ccn_name_from_uri(reqname, "ccnx:/ccnx");
02283 ccn_name_append(reqname, h->ccndid->buf, h->ccndid->length);
02284 ccn_name_append_str(reqname, "selfreg");
02285 fe->action = "selfreg";
02286 fe->ccnd_id = h->ccndid->buf;
02287 fe->ccnd_id_size = h->ccndid->length;
02288 fe->faceid = ~0;
02289 fe->name_prefix = ccn_charbuf_create();
02290 fe->flags = i->flags & 0xFF;
02291 fe->lifetime = -1;
02292 ccn_name_init(fe->name_prefix);
02293 ccn_name_append_components(fe->name_prefix, prefix, 0, prefix_size);
02294 reg_request = ccn_charbuf_create();
02295 ccnb_append_forwarding_entry(reg_request, fe);
02296 empty = ccn_charbuf_create();
02297 ccn_name_init(empty);
02298 signed_reg_request = ccn_charbuf_create();
02299 ccn_sign_content(h, signed_reg_request, empty, NULL,
02300 reg_request->buf, reg_request->length);
02301 ccn_name_append(reqname,
02302 signed_reg_request->buf, signed_reg_request->length);
02303
02304 ccn_express_interest(h, reqname, &p->action, templ);
02305 ccn_charbuf_destroy(&fe->name_prefix);
02306 ccn_charbuf_destroy(&reqname);
02307 ccn_charbuf_destroy(&templ);
02308 ccn_charbuf_destroy(®_request);
02309 ccn_charbuf_destroy(&signed_reg_request);
02310 ccn_charbuf_destroy(&empty);
02311 }
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322 int
02323 ccn_verify_content(struct ccn *h,
02324 const unsigned char *msg,
02325 struct ccn_parsed_ContentObject *pco)
02326 {
02327 struct ccn_pkey *pubkey = NULL;
02328 int res;
02329 unsigned char *buf = (unsigned char *)msg;
02330
02331 res = ccn_locate_key(h, msg, pco, &pubkey);
02332 if (res == 0) {
02333
02334 res = ccn_verify_signature(buf, pco->offset[CCN_PCO_E], pco, pubkey);
02335 res = (res == 1) ? 0 : -1;
02336 }
02337 return(res);
02338 }
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351 int
02352 ccn_load_private_key(struct ccn *h,
02353 const char *keystore_path,
02354 const char *keystore_passphrase,
02355 struct ccn_charbuf *pubid_out)
02356 {
02357 struct ccn_keystore *keystore = NULL;
02358 int res = 0;
02359 struct ccn_charbuf *pubid = pubid_out;
02360 struct ccn_charbuf *pubid_store = NULL;
02361 struct hashtb_enumerator ee;
02362 struct hashtb_enumerator *e = ⅇ
02363
02364 if (pubid == NULL)
02365 pubid = pubid_store = ccn_charbuf_create();
02366 if (pubid == NULL) {
02367 res = NOTE_ERRNO(h);
02368 goto Cleanup;
02369 }
02370 keystore = ccn_keystore_create();
02371 if (keystore == NULL) {
02372 res = NOTE_ERRNO(h);
02373 goto Cleanup;
02374 }
02375 res = ccn_keystore_init(keystore,
02376 (char *)keystore_path,
02377 (char *)keystore_passphrase);
02378 if (res != 0) {
02379 res = NOTE_ERRNO(h);
02380 goto Cleanup;
02381 }
02382 pubid->length = 0;
02383 ccn_charbuf_append(pubid,
02384 ccn_keystore_public_key_digest(keystore),
02385 ccn_keystore_public_key_digest_length(keystore));
02386 hashtb_start(h->keystores, e);
02387 res = hashtb_seek(e, pubid->buf, pubid->length, 0);
02388 if (res == HT_NEW_ENTRY) {
02389 struct ccn_keystore **p = e->data;
02390 *p = keystore;
02391 keystore = NULL;
02392 res = 0;
02393 }
02394 else if (res == HT_OLD_ENTRY)
02395 res = 0;
02396 else
02397 res = NOTE_ERRNO(h);
02398 hashtb_end(e);
02399 Cleanup:
02400 ccn_charbuf_destroy(&pubid_store);
02401 ccn_keystore_destroy(&keystore);
02402 return(res);
02403 }
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416 int
02417 ccn_load_default_key(struct ccn *h,
02418 const char *keystore_path,
02419 const char *keystore_passphrase)
02420 {
02421 struct ccn_charbuf *default_pubid = NULL;
02422 int res;
02423
02424 if (h->default_pubid != NULL)
02425 return(NOTE_ERR(h, EINVAL));
02426 default_pubid = ccn_charbuf_create();
02427 res = ccn_load_private_key(h,
02428 keystore_path,
02429 keystore_passphrase,
02430 default_pubid);
02431 if (res == 0)
02432 h->default_pubid = default_pubid;
02433 else
02434 ccn_charbuf_destroy(&default_pubid);
02435 return(res);
02436 }
02437
02438 static void
02439 finalize_keystore(struct hashtb_enumerator *e)
02440 {
02441 struct ccn_keystore **p = e->data;
02442 ccn_keystore_destroy(p);
02443 }
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454 int
02455 ccn_get_public_key(struct ccn *h,
02456 const struct ccn_signing_params *params,
02457 struct ccn_charbuf *digest_result,
02458 struct ccn_charbuf *result)
02459 {
02460 struct hashtb_enumerator ee;
02461 struct hashtb_enumerator *e = ⅇ
02462 struct ccn_keystore *keystore = NULL;
02463 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
02464 int res;
02465 res = ccn_chk_signing_params(h, params, &sp, NULL, NULL, NULL);
02466 if (res < 0)
02467 return(res);
02468 hashtb_start(h->keystores, e);
02469 if (hashtb_seek(e, sp.pubid, sizeof(sp.pubid), 0) == HT_OLD_ENTRY) {
02470 struct ccn_keystore **pk = e->data;
02471 keystore = *pk;
02472 if (digest_result != NULL) {
02473 digest_result->length = 0;
02474 ccn_charbuf_append(digest_result,
02475 ccn_keystore_public_key_digest(keystore),
02476 ccn_keystore_public_key_digest_length(keystore));
02477 }
02478 if (result != NULL) {
02479 struct ccn_buf_decoder decoder;
02480 struct ccn_buf_decoder *d;
02481 const unsigned char *p;
02482 size_t size;
02483 result->length = 0;
02484 ccn_append_pubkey_blob(result, ccn_keystore_public_key(keystore));
02485 d = ccn_buf_decoder_start(&decoder, result->buf, result->length);
02486 res = ccn_buf_match_blob(d, &p, &size);
02487 if (res >= 0) {
02488 memmove(result->buf, p, size);
02489 result->length = size;
02490 res = 0;
02491 }
02492 }
02493 }
02494 else {
02495 res = NOTE_ERR(h, -1);
02496 hashtb_delete(e);
02497 }
02498 hashtb_end(e);
02499 return(res);
02500 }
02501
02502
02503
02504
02505
02506 int
02507 ccn_chk_signing_params(struct ccn *h,
02508 const struct ccn_signing_params *params,
02509 struct ccn_signing_params *result,
02510 struct ccn_charbuf **ptimestamp,
02511 struct ccn_charbuf **pfinalblockid,
02512 struct ccn_charbuf **pkeylocator)
02513 {
02514 struct ccn_charbuf *default_pubid = NULL;
02515 struct ccn_charbuf *temp = NULL;
02516 const char *home = NULL;
02517 const char *ccnx_dir = NULL;
02518 int res = 0;
02519 int i;
02520 int conflicting;
02521 int needed;
02522
02523 if (params != NULL)
02524 *result = *params;
02525 if ((result->sp_flags & ~(CCN_SP_TEMPL_TIMESTAMP |
02526 CCN_SP_TEMPL_FINAL_BLOCK_ID |
02527 CCN_SP_TEMPL_FRESHNESS |
02528 CCN_SP_TEMPL_KEY_LOCATOR |
02529 CCN_SP_FINAL_BLOCK |
02530 CCN_SP_OMIT_KEY_LOCATOR
02531 )) != 0)
02532 return(NOTE_ERR(h, EINVAL));
02533 conflicting = CCN_SP_TEMPL_FINAL_BLOCK_ID | CCN_SP_FINAL_BLOCK;
02534 if ((result->sp_flags & conflicting) == conflicting)
02535 return(NOTE_ERR(h, EINVAL));
02536 conflicting = CCN_SP_TEMPL_KEY_LOCATOR | CCN_SP_OMIT_KEY_LOCATOR;
02537 if ((result->sp_flags & conflicting) == conflicting)
02538 return(NOTE_ERR(h, EINVAL));
02539 for (i = 0; i < sizeof(result->pubid) && result->pubid[i] == 0; i++)
02540 continue;
02541 if (i == sizeof(result->pubid)) {
02542 if (h->default_pubid == NULL) {
02543 default_pubid = ccn_charbuf_create();
02544 temp = ccn_charbuf_create();
02545 if (default_pubid == NULL || temp == NULL)
02546 return(NOTE_ERRNO(h));
02547 ccnx_dir = getenv("CCNX_DIR");
02548 if (ccnx_dir == NULL || ccnx_dir[0] == 0) {
02549 home = getenv("HOME");
02550 if (home == NULL)
02551 home = "";
02552 ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", home);
02553 }
02554 else
02555 ccn_charbuf_putf(temp, "%s/.ccnx_keystore", ccnx_dir);
02556 res = ccn_load_private_key(h,
02557 ccn_charbuf_as_string(temp),
02558 "Th1s1sn0t8g00dp8ssw0rd.",
02559 default_pubid);
02560 if (res == 0 && default_pubid->length == sizeof(result->pubid)) {
02561 h->default_pubid = default_pubid;
02562 default_pubid = NULL;
02563 }
02564 }
02565 if (h->default_pubid == NULL)
02566 res = NOTE_ERRNO(h);
02567 else
02568 memcpy(result->pubid, h->default_pubid->buf, sizeof(result->pubid));
02569 }
02570 ccn_charbuf_destroy(&default_pubid);
02571 ccn_charbuf_destroy(&temp);
02572 needed = result->sp_flags & (CCN_SP_TEMPL_TIMESTAMP |
02573 CCN_SP_TEMPL_FINAL_BLOCK_ID |
02574 CCN_SP_TEMPL_FRESHNESS |
02575 CCN_SP_TEMPL_KEY_LOCATOR );
02576 if (result->template_ccnb != NULL) {
02577 struct ccn_buf_decoder decoder;
02578 struct ccn_buf_decoder *d;
02579 size_t start;
02580 size_t stop;
02581 size_t size;
02582 const unsigned char *ptr = NULL;
02583 d = ccn_buf_decoder_start(&decoder,
02584 result->template_ccnb->buf,
02585 result->template_ccnb->length);
02586 if (ccn_buf_match_dtag(d, CCN_DTAG_SignedInfo)) {
02587 ccn_buf_advance(d);
02588 if (ccn_buf_match_dtag(d, CCN_DTAG_PublisherPublicKeyDigest))
02589 ccn_parse_required_tagged_BLOB(d,
02590 CCN_DTAG_PublisherPublicKeyDigest, 16, 64);
02591 start = d->decoder.token_index;
02592 ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Timestamp, 1, -1);
02593 stop = d->decoder.token_index;
02594 if ((needed & CCN_SP_TEMPL_TIMESTAMP) != 0) {
02595 i = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp,
02596 d->buf,
02597 start, stop,
02598 &ptr, &size);
02599 if (i == 0) {
02600 if (ptimestamp != NULL) {
02601 *ptimestamp = ccn_charbuf_create();
02602 ccn_charbuf_append(*ptimestamp, ptr, size);
02603 }
02604 needed &= ~CCN_SP_TEMPL_TIMESTAMP;
02605 }
02606 }
02607 ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Type, 1, -1);
02608 i = ccn_parse_optional_tagged_nonNegativeInteger(d,
02609 CCN_DTAG_FreshnessSeconds);
02610 if ((needed & CCN_SP_TEMPL_FRESHNESS) != 0 && i >= 0) {
02611 result->freshness = i;
02612 needed &= ~CCN_SP_TEMPL_FRESHNESS;
02613 }
02614 if (ccn_buf_match_dtag(d, CCN_DTAG_FinalBlockID)) {
02615 ccn_buf_advance(d);
02616 start = d->decoder.token_index;
02617 if (ccn_buf_match_some_blob(d))
02618 ccn_buf_advance(d);
02619 stop = d->decoder.token_index;
02620 ccn_buf_check_close(d);
02621 if ((needed & CCN_SP_TEMPL_FINAL_BLOCK_ID) != 0 &&
02622 d->decoder.state >= 0 && stop > start) {
02623 if (pfinalblockid != NULL) {
02624 *pfinalblockid = ccn_charbuf_create();
02625 ccn_charbuf_append(*pfinalblockid,
02626 d->buf + start, stop - start);
02627 }
02628 needed &= ~CCN_SP_TEMPL_FINAL_BLOCK_ID;
02629 }
02630 }
02631 start = d->decoder.token_index;
02632 if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator))
02633 ccn_buf_advance_past_element(d);
02634 stop = d->decoder.token_index;
02635 if ((needed & CCN_SP_TEMPL_KEY_LOCATOR) != 0 &&
02636 d->decoder.state >= 0 && stop > start) {
02637 if (pkeylocator != NULL) {
02638 *pkeylocator = ccn_charbuf_create();
02639 ccn_charbuf_append(*pkeylocator,
02640 d->buf + start, stop - start);
02641 }
02642 needed &= ~CCN_SP_TEMPL_KEY_LOCATOR;
02643 }
02644 ccn_buf_check_close(d);
02645 }
02646 if (d->decoder.state < 0)
02647 res = NOTE_ERR(h, EINVAL);
02648 }
02649 if (needed != 0)
02650 res = NOTE_ERR(h, EINVAL);
02651 return(res);
02652 }
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665 int
02666 ccn_sign_content(struct ccn *h,
02667 struct ccn_charbuf *resultbuf,
02668 const struct ccn_charbuf *name_prefix,
02669 const struct ccn_signing_params *params,
02670 const void *data, size_t size)
02671 {
02672 struct hashtb_enumerator ee;
02673 struct hashtb_enumerator *e = ⅇ
02674 struct ccn_signing_params p = CCN_SIGNING_PARAMS_INIT;
02675 struct ccn_charbuf *signed_info = NULL;
02676 struct ccn_keystore *keystore = NULL;
02677 struct ccn_charbuf *timestamp = NULL;
02678 struct ccn_charbuf *finalblockid = NULL;
02679 struct ccn_charbuf *keylocator = NULL;
02680 int res;
02681
02682 res = ccn_chk_signing_params(h, params, &p,
02683 ×tamp, &finalblockid, &keylocator);
02684 if (res < 0)
02685 return(res);
02686 hashtb_start(h->keystores, e);
02687 if (hashtb_seek(e, p.pubid, sizeof(p.pubid), 0) == HT_OLD_ENTRY) {
02688 struct ccn_keystore **pk = e->data;
02689 keystore = *pk;
02690 signed_info = ccn_charbuf_create();
02691 if (keylocator == NULL && (p.sp_flags & CCN_SP_OMIT_KEY_LOCATOR) == 0) {
02692
02693 keylocator = ccn_charbuf_create();
02694 ccn_charbuf_append_tt(keylocator, CCN_DTAG_KeyLocator, CCN_DTAG);
02695 ccn_charbuf_append_tt(keylocator, CCN_DTAG_Key, CCN_DTAG);
02696 res = ccn_append_pubkey_blob(keylocator,
02697 ccn_keystore_public_key(keystore));
02698 ccn_charbuf_append_closer(keylocator);
02699 ccn_charbuf_append_closer(keylocator);
02700 }
02701 if (res >= 0 && (p.sp_flags & CCN_SP_FINAL_BLOCK) != 0) {
02702 int ncomp;
02703 struct ccn_indexbuf *ndx;
02704 const unsigned char *comp = NULL;
02705 size_t size = 0;
02706
02707 ndx = ccn_indexbuf_create();
02708 ncomp = ccn_name_split(name_prefix, ndx);
02709 if (ncomp < 0)
02710 res = NOTE_ERR(h, EINVAL);
02711 else {
02712 finalblockid = ccn_charbuf_create();
02713 ccn_name_comp_get(name_prefix->buf,
02714 ndx, ncomp - 1, &comp, &size);
02715 ccn_charbuf_append_tt(finalblockid, size, CCN_BLOB);
02716 ccn_charbuf_append(finalblockid, comp, size);
02717 }
02718 ccn_indexbuf_destroy(&ndx);
02719 }
02720 if (res >= 0)
02721 res = ccn_signed_info_create(signed_info,
02722 ccn_keystore_public_key_digest(keystore),
02723 ccn_keystore_public_key_digest_length(keystore),
02724 timestamp,
02725 p.type,
02726 p.freshness,
02727 finalblockid,
02728 keylocator);
02729 if (res >= 0)
02730 res = ccn_encode_ContentObject(resultbuf,
02731 name_prefix,
02732 signed_info,
02733 data,
02734 size,
02735 ccn_keystore_digest_algorithm(keystore),
02736 ccn_keystore_private_key(keystore));
02737 }
02738 else {
02739 res = NOTE_ERR(h, -1);
02740 hashtb_delete(e);
02741 }
02742 hashtb_end(e);
02743 ccn_charbuf_destroy(×tamp);
02744 ccn_charbuf_destroy(&keylocator);
02745 ccn_charbuf_destroy(&finalblockid);
02746 ccn_charbuf_destroy(&signed_info);
02747 return(res);
02748 }
02749
02750
02751
02752
02753
02754
02755 int
02756 ccn_is_final_block(struct ccn_upcall_info *info)
02757 {
02758 const unsigned char *ccnb;
02759 size_t ccnb_size;
02760 int res;
02761 ccnb = info->content_ccnb;
02762 if (ccnb == NULL || info->pco == NULL)
02763 return(0);
02764 ccnb_size = info->pco->offset[CCN_PCO_E];
02765 if (info->pco->offset[CCN_PCO_B_FinalBlockID] !=
02766 info->pco->offset[CCN_PCO_E_FinalBlockID]) {
02767 const unsigned char *finalid = NULL;
02768 size_t finalid_size = 0;
02769 const unsigned char *nameid = NULL;
02770 size_t nameid_size = 0;
02771 struct ccn_indexbuf *cc = info->content_comps;
02772 if (cc->n < 2) return(-1);
02773 res = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb,
02774 info->pco->offset[CCN_PCO_B_FinalBlockID],
02775 info->pco->offset[CCN_PCO_E_FinalBlockID],
02776 &finalid,
02777 &finalid_size);
02778 if (res < 0) return(-1);
02779 res = ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb,
02780 cc->buf[cc->n - 2],
02781 cc->buf[cc->n - 1],
02782 &nameid,
02783 &nameid_size);
02784 if (res < 0) return(-1);
02785 if (finalid_size == nameid_size &&
02786 0 == memcmp(finalid, nameid, nameid_size))
02787 return(1);
02788 }
02789 return(0);
02790 }