00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <stdarg.h>
00023 #include <limits.h>
00024 #include <string.h>
00025 #include <strings.h>
00026 #include <unistd.h>
00027 #include <sys/socket.h>
00028 #include <sys/time.h>
00029 #include <netdb.h>
00030 #include <netinet/in.h>
00031 #define BIND_8_COMPAT
00032 #include <arpa/nameser.h>
00033 #include <resolv.h>
00034 #include <errno.h>
00035 #include <ccn/bloom.h>
00036 #include <ccn/ccn.h>
00037 #include <ccn/ccnd.h>
00038 #include <ccn/charbuf.h>
00039 #include <ccn/uri.h>
00040 #include <ccn/face_mgmt.h>
00041 #include <ccn/reg_mgmt.h>
00042 #include <ccn/sockcreate.h>
00043 #include <ccn/signing.h>
00044
00045 #if defined(NEED_GETADDRINFO_COMPAT)
00046 #include "getaddrinfo.h"
00047 #include "dummyin6.h"
00048 #endif
00049
00050 #ifndef AI_ADDRCONFIG
00051 #define AI_ADDRCONFIG 0
00052 #endif
00053
00054 #ifndef NS_MAXMSG
00055 #define NS_MAXMSG 65535
00056 #endif
00057
00058 #ifndef NS_MAXDNAME
00059 #ifdef MAXDNAME
00060 #define NS_MAXDNAME MAXDNAME
00061 #endif
00062 #endif
00063
00064 #ifndef T_SRV
00065 #define T_SRV 33
00066 #endif
00067
00068 #define OP_REG 0
00069 #define OP_UNREG 1
00070
00071
00072
00073
00074 struct prefix_face_list_item {
00075 struct ccn_charbuf *prefix;
00076 struct ccn_face_instance *fi;
00077 int flags;
00078 struct prefix_face_list_item *next;
00079 };
00080
00081
00082
00083
00084 static struct ccn_charbuf *local_scope_template = NULL;
00085 static struct ccn_charbuf *no_name = NULL;
00086 static unsigned char ccndid_storage[32] = {0};
00087 static const unsigned char *ccndid = ccndid_storage;
00088 static size_t ccndid_size = 0;
00089
00090
00091
00092
00093 int verbose = 0;
00094
00095
00096 static void
00097 usage(const char *progname)
00098 {
00099 fprintf(stderr,
00100 "%s [-d] [-v] (-f configfile | (add|del) uri (udp|tcp) host [port [flags [mcastttl [mcastif]]]])\n"
00101 " -d enter dynamic mode and create FIB entries based on DNS SRV records\n"
00102 " -f configfile add or delete FIB entries based on contents of configfile\n"
00103 " -v increase logging level\n"
00104 " add|del add or delete FIB entry based on parameters\n"
00105 "%s [-v] destroyface faceid\n"
00106 " destroy face based on face number\n",
00107 progname,
00108 progname);
00109 exit(1);
00110 }
00111
00112 void
00113 ccndc_warn(int lineno, const char *format, ...)
00114 {
00115 struct timeval t;
00116 va_list ap;
00117 va_start(ap, format);
00118 gettimeofday(&t, NULL);
00119 fprintf(stderr, "%d.%06d ccndc[%d]:%d: ", (int)t.tv_sec, (unsigned)t.tv_usec, (int)getpid(), lineno);
00120 vfprintf(stderr, format, ap);
00121 va_end(ap);
00122 }
00123
00124 void
00125 ccndc_fatal(int line, const char *format, ...)
00126 {
00127 struct timeval t;
00128 va_list ap;
00129 va_start(ap, format);
00130 gettimeofday(&t, NULL);
00131 fprintf(stderr, "%d.%06d ccndc[%d]:%d: ", (int)t.tv_sec, (unsigned)t.tv_usec, (int)getpid(), line);
00132 vfprintf(stderr, format, ap);
00133 va_end(ap);
00134 exit(1);
00135 }
00136
00137 #define ON_ERROR_EXIT(resval, msg) on_error_exit((resval), __LINE__, msg)
00138
00139 static void
00140 on_error_exit(int res, int lineno, const char *msg)
00141 {
00142 if (res >= 0)
00143 return;
00144 ccndc_fatal(lineno, "fatal error, res = %d, %s\n", res, msg);
00145 }
00146
00147 #define ON_ERROR_CLEANUP(resval) \
00148 { \
00149 if ((resval) < 0) { \
00150 if (verbose > 0) ccndc_warn (__LINE__, "OnError cleanup\n"); \
00151 goto Cleanup; \
00152 } \
00153 }
00154
00155 #define ON_NULL_CLEANUP(resval) \
00156 { \
00157 if ((resval) == NULL) { \
00158 if (verbose > 0) ccndc_warn(__LINE__, "OnNull cleanup\n"); \
00159 goto Cleanup; \
00160 } \
00161 }
00162
00163 static void
00164 initialize_global_data(void) {
00165 const char *msg = "Unable to initialize global data.";
00166
00167 local_scope_template = ccn_charbuf_create();
00168 if (local_scope_template == NULL) {
00169 ON_ERROR_EXIT(-1, msg);
00170 }
00171
00172 ON_ERROR_EXIT(ccn_charbuf_append_tt(local_scope_template, CCN_DTAG_Interest, CCN_DTAG), msg);
00173 ON_ERROR_EXIT(ccn_charbuf_append_tt(local_scope_template, CCN_DTAG_Name, CCN_DTAG), msg);
00174 ON_ERROR_EXIT(ccn_charbuf_append_closer(local_scope_template), msg);
00175 ON_ERROR_EXIT(ccnb_tagged_putf(local_scope_template, CCN_DTAG_Scope, "1"), msg);
00176 ON_ERROR_EXIT(ccn_charbuf_append_closer(local_scope_template), msg);
00177
00178
00179 no_name = ccn_charbuf_create();
00180 if (no_name == NULL) {
00181 ON_ERROR_EXIT(-1, msg);
00182 }
00183 ON_ERROR_EXIT(ccn_name_init(no_name), msg);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 static int
00193 get_ccndid(struct ccn *h, const unsigned char *ccndid, size_t ccndid_storage_size)
00194 {
00195
00196 struct ccn_charbuf *name = NULL;
00197 struct ccn_charbuf *resultbuf = NULL;
00198 struct ccn_parsed_ContentObject pcobuf = {0};
00199 char ccndid_uri[] = "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY";
00200 const unsigned char *ccndid_result;
00201 static size_t ccndid_result_size;
00202 int res;
00203
00204 name = ccn_charbuf_create();
00205 if (name == NULL) {
00206 ON_ERROR_EXIT(-1, "Unable to allocate storage for service locator name charbuf");
00207 }
00208
00209 resultbuf = ccn_charbuf_create();
00210 if (resultbuf == NULL) {
00211 ON_ERROR_EXIT(-1, "Unable to allocate storage for result charbuf");
00212 }
00213
00214
00215 ON_ERROR_EXIT(ccn_name_from_uri(name, ccndid_uri), "Unable to parse service locator URI for ccnd key");
00216 ON_ERROR_EXIT(ccn_get(h, name, local_scope_template, 4500, resultbuf, &pcobuf, NULL, 0), "Unable to get key from ccnd");
00217 res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest,
00218 resultbuf->buf,
00219 pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest],
00220 pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest],
00221 &ccndid_result, &ccndid_result_size);
00222 ON_ERROR_EXIT(res, "Unable to parse ccnd response for ccnd id");
00223 if (ccndid_result_size > ccndid_storage_size)
00224 ON_ERROR_EXIT(-1, "Incorrect size for ccnd id in response");
00225 memcpy((void *)ccndid, ccndid_result, ccndid_result_size);
00226 ccn_charbuf_destroy(&name);
00227 ccn_charbuf_destroy(&resultbuf);
00228 return (ccndid_result_size);
00229 }
00230
00231 static struct prefix_face_list_item *prefix_face_list_item_create(struct ccn_charbuf *prefix,
00232 int ipproto,
00233 int mcast_ttl,
00234 char *host,
00235 char *port,
00236 char *mcastif,
00237 int lifetime,
00238 int flags,
00239 int create,
00240 unsigned faceid)
00241 {
00242 struct prefix_face_list_item *pfl = calloc(1, sizeof(struct prefix_face_list_item));
00243 struct ccn_face_instance *fi = calloc(1, sizeof(*fi));
00244 struct ccn_charbuf *store = ccn_charbuf_create();
00245 int host_off = -1;
00246 int port_off = -1;
00247 int mcast_off = -1;
00248
00249 if (pfl == NULL || fi == NULL || store == NULL) {
00250 if (pfl) free(pfl);
00251 if (fi) ccn_face_instance_destroy(&fi);
00252 if (store) ccn_charbuf_destroy(&store);
00253 return (NULL);
00254 }
00255 pfl->fi = fi;
00256 pfl->fi->store = store;
00257
00258 pfl->prefix = prefix;
00259 pfl->fi->descr.ipproto = ipproto;
00260 pfl->fi->descr.mcast_ttl = mcast_ttl;
00261 pfl->fi->lifetime = lifetime;
00262 if (faceid > 0)
00263 pfl->fi->faceid = faceid;
00264 pfl->flags = flags;
00265
00266 if (create) {
00267 ccn_charbuf_append(store, "newface", strlen("newface") + 1);
00268 }
00269 else {
00270 ccn_charbuf_append(store, "destroyface", strlen("destroyface") + 1);
00271 }
00272
00273 host_off = store->length;
00274 ccn_charbuf_append(store, host, strlen(host) + 1);
00275 port_off = store->length;
00276 ccn_charbuf_append(store, port, strlen(port) + 1);
00277 if (mcastif != NULL) {
00278 mcast_off = store->length;
00279 ccn_charbuf_append(store, mcastif, strlen(mcastif) + 1);
00280 }
00281
00282
00283 char *b = (char *)store->buf;
00284 pfl->fi->action = b;
00285 pfl->fi->descr.address = b + host_off;
00286 pfl->fi->descr.port = b + port_off;
00287 pfl->fi->descr.source_address = (mcast_off == -1) ? NULL : b + mcast_off;
00288
00289 return (pfl);
00290 }
00291
00292 static void prefix_face_list_destroy(struct prefix_face_list_item **pflpp)
00293 {
00294 struct prefix_face_list_item *pflp = *pflpp;
00295 struct prefix_face_list_item *next;
00296
00297 if (pflp == NULL) return;
00298 while (pflp) {
00299 ccn_face_instance_destroy(&pflp->fi);
00300 ccn_charbuf_destroy(&pflp->prefix);
00301 next = pflp->next;
00302 free(pflp);
00303 pflp = next;
00304 }
00305 *pflpp = NULL;
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315 static struct ccn_face_instance *
00316 do_face_action(struct ccn *h, struct ccn_face_instance *face_instance)
00317 {
00318 struct ccn_charbuf *newface = NULL;
00319 struct ccn_charbuf *signed_info = NULL;
00320 struct ccn_charbuf *temp = NULL;
00321 struct ccn_charbuf *name = NULL;
00322 struct ccn_charbuf *resultbuf = NULL;
00323 struct ccn_parsed_ContentObject pcobuf = {0};
00324 struct ccn_face_instance *new_face_instance = NULL;
00325 const unsigned char *ptr = NULL;
00326 size_t length = 0;
00327 int res = 0;
00328
00329
00330 newface = ccn_charbuf_create();
00331 ON_NULL_CLEANUP(newface);
00332 ON_ERROR_CLEANUP(ccnb_append_face_instance(newface, face_instance));
00333
00334 temp = ccn_charbuf_create();
00335 ON_NULL_CLEANUP(temp);
00336 res = ccn_sign_content(h, temp, no_name, NULL, newface->buf, newface->length);
00337 ON_ERROR_CLEANUP(res);
00338 resultbuf = ccn_charbuf_create();
00339 ON_NULL_CLEANUP(resultbuf);
00340
00341
00342 name = ccn_charbuf_create();
00343 ON_NULL_CLEANUP(name);
00344 ON_ERROR_CLEANUP(ccn_name_init(name));
00345 ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx"));
00346 ON_ERROR_CLEANUP(ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size));
00347 ON_ERROR_CLEANUP(ccn_name_append_str(name, face_instance->action));
00348 ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length));
00349 res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0);
00350 ON_ERROR_CLEANUP(res);
00351
00352 ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length));
00353 new_face_instance = ccn_face_instance_parse(ptr, length);
00354 ON_NULL_CLEANUP(new_face_instance);
00355 ccn_charbuf_destroy(&newface);
00356 ccn_charbuf_destroy(&signed_info);
00357 ccn_charbuf_destroy(&temp);
00358 ccn_charbuf_destroy(&resultbuf);
00359 ccn_charbuf_destroy(&name);
00360 return (new_face_instance);
00361
00362 Cleanup:
00363 ccn_charbuf_destroy(&newface);
00364 ccn_charbuf_destroy(&signed_info);
00365 ccn_charbuf_destroy(&temp);
00366 ccn_charbuf_destroy(&resultbuf);
00367 ccn_charbuf_destroy(&name);
00368 ccn_face_instance_destroy(&new_face_instance);
00369 return (NULL);
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379 static int
00380 register_unregister_prefix(struct ccn *h,
00381 int operation,
00382 struct ccn_charbuf *name_prefix,
00383 struct ccn_face_instance *face_instance,
00384 int flags)
00385 {
00386 struct ccn_charbuf *temp = NULL;
00387 struct ccn_charbuf *resultbuf = NULL;
00388 struct ccn_charbuf *signed_info = NULL;
00389 struct ccn_charbuf *name = NULL;
00390 struct ccn_charbuf *prefixreg = NULL;
00391 struct ccn_parsed_ContentObject pcobuf = {0};
00392 struct ccn_forwarding_entry forwarding_entry_storage = {0};
00393 struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage;
00394 struct ccn_forwarding_entry *new_forwarding_entry;
00395 const unsigned char *ptr = NULL;
00396 size_t length = 0;
00397 int res;
00398
00399
00400 forwarding_entry->action = (operation == OP_REG) ? "prefixreg" : "unreg";
00401 forwarding_entry->name_prefix = name_prefix;
00402 forwarding_entry->ccnd_id = face_instance->ccnd_id;
00403 forwarding_entry->ccnd_id_size = face_instance->ccnd_id_size;
00404 forwarding_entry->faceid = face_instance->faceid;
00405 forwarding_entry->flags = flags;
00406 forwarding_entry->lifetime = (~0U) >> 1;
00407
00408 prefixreg = ccn_charbuf_create();
00409 ON_NULL_CLEANUP(prefixreg);
00410 ON_ERROR_CLEANUP(ccnb_append_forwarding_entry(prefixreg, forwarding_entry));
00411 temp = ccn_charbuf_create();
00412 ON_NULL_CLEANUP(temp);
00413 res = ccn_sign_content(h, temp, no_name, NULL, prefixreg->buf, prefixreg->length);
00414 ON_ERROR_CLEANUP(res);
00415 resultbuf = ccn_charbuf_create();
00416 ON_NULL_CLEANUP(resultbuf);
00417 name = ccn_charbuf_create();
00418 ON_ERROR_CLEANUP(ccn_name_init(name));
00419 ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx"));
00420 ON_ERROR_CLEANUP(ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size));
00421 ON_ERROR_CLEANUP(ccn_name_append_str(name, (operation == OP_REG) ? "prefixreg" : "unreg"));
00422 ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length));
00423 res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0);
00424 ON_ERROR_CLEANUP(res);
00425 ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length));
00426 new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length);
00427 ON_NULL_CLEANUP(new_forwarding_entry);
00428
00429 res = new_forwarding_entry->faceid;
00430
00431 ccn_forwarding_entry_destroy(&new_forwarding_entry);
00432 ccn_charbuf_destroy(&signed_info);
00433 ccn_charbuf_destroy(&temp);
00434 ccn_charbuf_destroy(&resultbuf);
00435 ccn_charbuf_destroy(&name);
00436 ccn_charbuf_destroy(&prefixreg);
00437
00438 return (res);
00439
00440
00441
00442
00443 Cleanup:
00444 ccn_charbuf_destroy(&signed_info);
00445 ccn_charbuf_destroy(&temp);
00446 ccn_charbuf_destroy(&resultbuf);
00447 ccn_charbuf_destroy(&name);
00448 ccn_charbuf_destroy(&prefixreg);
00449
00450 return (-1);
00451 }
00452
00453 static int
00454 process_command_tokens(struct prefix_face_list_item *pfltail,
00455 int lineno,
00456 char *cmd,
00457 char *uri,
00458 char *proto,
00459 char *host,
00460 char *port,
00461 char *flags,
00462 char *mcastttl,
00463 char *mcastif)
00464 {
00465 int lifetime = 0;
00466 struct ccn_charbuf *prefix = NULL;
00467 int ipproto = 0;
00468 int socktype = 0;
00469 int iflags = 0;
00470 int imcastttl = 0;
00471 int createface = 0;
00472 int facenumber = 0;
00473 char rhostnamebuf[NI_MAXHOST];
00474 char rhostportbuf[NI_MAXSERV];
00475 struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG)};
00476 struct addrinfo mcasthints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG | AI_NUMERICHOST)};
00477 struct addrinfo *raddrinfo = NULL;
00478 struct addrinfo *mcastifaddrinfo = NULL;
00479 struct prefix_face_list_item *pflp = NULL;
00480 int res;
00481
00482 if (cmd == NULL) {
00483 ccndc_warn(__LINE__, "command error (line %d), missing command\n", lineno);
00484 return (-1);
00485 }
00486 createface = 1;
00487 if (strcasecmp(cmd, "add") == 0)
00488 lifetime = (~0U) >> 1;
00489 else if (strcasecmp(cmd, "del") == 0)
00490 lifetime = 0;
00491 else if (strcasecmp(cmd, "destroyface") == 0)
00492 createface = 0;
00493 else {
00494 ccndc_warn(__LINE__, "command error (line %d), unrecognized command '%s'\n", lineno, cmd);
00495 return (-1);
00496 }
00497 if (createface) {
00498
00499 if (uri == NULL) {
00500 ccndc_warn(__LINE__, "command error (line %d), missing CCNx URI\n", lineno);
00501 return (-1);
00502 }
00503 prefix = ccn_charbuf_create();
00504 res = ccn_name_from_uri(prefix, uri);
00505 if (res < 0) {
00506 ccndc_warn(__LINE__, "command error (line %d), bad CCNx URI '%s'\n", lineno, uri);
00507 return (-1);
00508 }
00509
00510 if (proto == NULL) {
00511 ccndc_warn(__LINE__, "command error (line %d), missing address type\n", lineno);
00512 return (-1);
00513 }
00514 if (strcasecmp(proto, "udp") == 0) {
00515 ipproto = IPPROTO_UDP;
00516 socktype = SOCK_DGRAM;
00517 }
00518 else if (strcasecmp(proto, "tcp") == 0) {
00519 ipproto = IPPROTO_TCP;
00520 socktype = SOCK_STREAM;
00521 }
00522 else {
00523 ccndc_warn(__LINE__, "command error (line %d), unrecognized address type '%s'\n", lineno, proto);
00524 return (-1);
00525 }
00526
00527 if (host == NULL) {
00528 ccndc_warn(__LINE__, "command error (line %d), missing hostname\n", lineno);
00529 return (-1);
00530 }
00531
00532 if (port == NULL || port[0] == 0)
00533 port = CCN_DEFAULT_UNICAST_PORT;
00534
00535 hints.ai_socktype = socktype;
00536 res = getaddrinfo(host, port, &hints, &raddrinfo);
00537 if (res != 0 || raddrinfo == NULL) {
00538 ccndc_warn(__LINE__, "command error (line %d), getaddrinfo: %s\n", lineno, gai_strerror(res));
00539 return (-1);
00540 }
00541 res = getnameinfo(raddrinfo->ai_addr, raddrinfo->ai_addrlen,
00542 rhostnamebuf, sizeof(rhostnamebuf),
00543 rhostportbuf, sizeof(rhostportbuf),
00544 NI_NUMERICHOST | NI_NUMERICSERV);
00545 freeaddrinfo(raddrinfo);
00546 if (res != 0) {
00547 ccndc_warn(__LINE__, "command error (line %d), getnameinfo: %s\n", lineno, gai_strerror(res));
00548 return (-1);
00549 }
00550
00551 iflags = -1;
00552 if (flags != NULL && flags[0] != 0) {
00553 iflags = atoi(flags);
00554 if ((iflags & ~CCN_FORW_PUBMASK) != 0) {
00555 ccndc_warn(__LINE__, "command error (line %d), invalid flags 0x%x\n", lineno, iflags);
00556 return (-1);
00557 }
00558 }
00559
00560 imcastttl = -1;
00561 if (mcastttl != NULL) {
00562 imcastttl = atoi(mcastttl);
00563 if (imcastttl < 0 || imcastttl > 255) {
00564 ccndc_warn(__LINE__, "command error (line %d), invalid multicast ttl: %s\n", lineno, mcastttl);
00565 return (-1);
00566 }
00567 }
00568
00569 if (mcastif != NULL) {
00570 res = getaddrinfo(mcastif, NULL, &mcasthints, &mcastifaddrinfo);
00571 if (res != 0) {
00572 ccndc_warn(__LINE__, "command error (line %d), mcastifaddr getaddrinfo: %s\n", lineno, gai_strerror(res));
00573 return (-1);
00574 }
00575 }
00576 } else {
00577
00578 if (uri == NULL) {
00579 ccndc_warn(__LINE__, "command error (line %d), missing face number for destroyface\n", lineno);
00580 return (-1);
00581 }
00582 facenumber = atoi(uri);
00583 if (facenumber < 0) {
00584 ccndc_warn(__LINE__, "command error (line %d), invalid face number for destroyface: %d\n", lineno, facenumber);
00585 return (-1);
00586 }
00587
00588 }
00589
00590 pflp = prefix_face_list_item_create(prefix, ipproto, imcastttl, rhostnamebuf,
00591 rhostportbuf, mcastif, lifetime, iflags,
00592 createface, facenumber);
00593 if (pflp == NULL) {
00594 ccndc_fatal(__LINE__, "Unable to allocate prefix_face_list_item\n");
00595 }
00596 pfltail->next = pflp;
00597 return (0);
00598 }
00599
00600 static int
00601 read_configfile(const char *filename, struct prefix_face_list_item *pfltail)
00602 {
00603 int configerrors = 0;
00604 int lineno = 0;
00605 char *cmd;
00606 char *uri;
00607 char *proto;
00608 char *host;
00609 char *port;
00610 char *flags;
00611 char *mcastttl;
00612 char *mcastif;
00613 FILE *cfg;
00614 char buf[1024];
00615 const char *seps = " \t\n";
00616 char *cp = NULL;
00617 char *last = NULL;
00618 int res;
00619
00620 cfg = fopen(filename, "r");
00621 if (cfg == NULL)
00622 ccndc_fatal(__LINE__, "%s (%s)\n", strerror(errno), filename);
00623
00624 while (fgets((char *)buf, sizeof(buf), cfg)) {
00625 int len;
00626 lineno++;
00627 len = strlen(buf);
00628 if (buf[0] == '#' || len == 0)
00629 continue;
00630 if (buf[len - 1] == '\n')
00631 buf[len - 1] = '\0';
00632 cp = index(buf, '#');
00633 if (cp != NULL)
00634 *cp = '\0';
00635
00636 cmd = strtok_r(buf, seps, &last);
00637 if (cmd == NULL)
00638 continue;
00639 uri = strtok_r(NULL, seps, &last);
00640 proto = strtok_r(NULL, seps, &last);
00641 host = strtok_r(NULL, seps, &last);
00642 port = strtok_r(NULL, seps, &last);
00643 flags = strtok_r(NULL, seps, &last);
00644 mcastttl = strtok_r(NULL, seps, &last);
00645 mcastif = strtok_r(NULL, seps, &last);
00646 res = process_command_tokens(pfltail, lineno, cmd, uri, proto, host, port, flags, mcastttl, mcastif);
00647 if (res < 0) {
00648 configerrors--;
00649 } else {
00650 pfltail = pfltail->next;
00651 }
00652 }
00653 fclose(cfg);
00654 return (configerrors);
00655 }
00656 int query_srv(const unsigned char *domain, int domain_size,
00657 char **hostp, int *portp, char **proto)
00658 {
00659 union {
00660 HEADER header;
00661 unsigned char buf[NS_MAXMSG];
00662 } ans;
00663 ssize_t ans_size;
00664 char srv_name[NS_MAXDNAME];
00665 int qdcount, ancount, i;
00666 unsigned char *msg, *msgend;
00667 unsigned char *end;
00668 int type = 0, class = 0, ttl = 0, size = 0, priority = 0, weight = 0, port = 0, minpriority;
00669 char host[NS_MAXDNAME];
00670
00671 res_init();
00672
00673
00674
00675
00676
00677 *proto = "tcp";
00678 snprintf(srv_name, sizeof(srv_name), "_ccnx._tcp.%.*s", (int)domain_size, domain);
00679 ans_size = res_query(srv_name, C_IN, T_SRV, ans.buf, sizeof(ans.buf));
00680 if (ans_size < 0) {
00681 *proto = "udp";
00682 snprintf(srv_name, sizeof(srv_name), "_ccnx._udp.%.*s", (int)domain_size, domain);
00683 ans_size = res_query(srv_name, C_IN, T_SRV, ans.buf, sizeof(ans.buf));
00684 if (ans_size < 0)
00685 return (-1);
00686 }
00687 if (ans_size > sizeof(ans.buf))
00688 return (-1);
00689
00690
00691 qdcount = ntohs(ans.header.qdcount);
00692 ancount = ntohs(ans.header.ancount);
00693 msg = ans.buf + sizeof(ans.header);
00694 msgend = ans.buf + ans_size;
00695
00696 for (i = qdcount; i > 0; --i) {
00697 if ((size = dn_skipname(msg, msgend)) < 0)
00698 return (-1);
00699 msg = msg + size + QFIXEDSZ;
00700 }
00701
00702
00703
00704
00705
00706 minpriority = INT_MAX;
00707 for (i = ancount; i > 0; --i) {
00708 size = dn_expand(ans.buf, msgend, msg, srv_name, sizeof (srv_name));
00709 if (size < 0)
00710 return (CCN_UPCALL_RESULT_ERR);
00711 msg = msg + size;
00712 GETSHORT(type, msg);
00713 GETSHORT(class, msg);
00714 GETLONG(ttl, msg);
00715 GETSHORT(size, msg);
00716 if ((end = msg + size) > msgend)
00717 return (-1);
00718
00719 if (type != T_SRV) {
00720 msg = end;
00721 continue;
00722 }
00723
00724
00725
00726
00727
00728
00729 GETSHORT(priority, msg);
00730 if (priority < minpriority) {
00731 minpriority = priority;
00732 GETSHORT(weight, msg);
00733 GETSHORT(port, msg);
00734 size = dn_expand(ans.buf, msgend, msg, host, sizeof (host));
00735 if (size < 0)
00736 return (-1);
00737 }
00738 msg = end;
00739 }
00740 if (hostp) {
00741 size = strlen(host);
00742 *hostp = calloc(1, size);
00743 if (!*hostp)
00744 return (-1);
00745 strncpy(*hostp, host, size);
00746 }
00747 if (portp) {
00748 *portp = port;
00749 }
00750 return (0);
00751 }
00752
00753 void
00754 process_prefix_face_list_item(struct ccn *h,
00755 struct prefix_face_list_item *pfl)
00756 {
00757 struct ccn_face_instance *nfi;
00758 struct ccn_charbuf *temp;
00759 int op;
00760 int createface;
00761 int res;
00762
00763 op = (pfl->fi->lifetime > 0) ? OP_REG : OP_UNREG;
00764 pfl->fi->ccnd_id = ccndid;
00765 pfl->fi->ccnd_id_size = ccndid_size;
00766 createface = 0 == strcmp(pfl->fi->action, "newface");
00767 nfi = do_face_action(h, pfl->fi);
00768 if (!createface) {
00769 if (nfi == NULL) {
00770 ccndc_warn(__LINE__, "Unable to destroy face %d\n",
00771 pfl->fi->faceid);
00772 return;
00773 }
00774 } else {
00775 if (nfi == NULL) {
00776 temp = ccn_charbuf_create();
00777 ccn_uri_append(temp, pfl->prefix->buf, pfl->prefix->length, 1);
00778 ccndc_warn(__LINE__, "Unable to create face for %s %s %s %s %s\n",
00779 (op == OP_REG) ? "add" : "del", ccn_charbuf_as_string(temp),
00780 (pfl->fi->descr.ipproto == IPPROTO_UDP) ? "udp" : "tcp",
00781 pfl->fi->descr.address,
00782 pfl->fi->descr.port);
00783 ccn_charbuf_destroy(&temp);
00784 return;
00785 }
00786 res = register_unregister_prefix(h, op, pfl->prefix, nfi, pfl->flags);
00787 if (res < 0) {
00788 temp = ccn_charbuf_create();
00789 ccn_uri_append(temp, pfl->prefix->buf, pfl->prefix->length, 1);
00790 ccndc_warn(__LINE__, "Unable to %sregister prefix on face %d for %s %s %s %s %s\n",
00791 (op == OP_UNREG) ? "un" : "", nfi->faceid,
00792 (op == OP_REG) ? "add" : "del",
00793 ccn_charbuf_as_string(temp),
00794 (pfl->fi->descr.ipproto == IPPROTO_UDP) ? "udp" : "tcp",
00795 pfl->fi->descr.address,
00796 pfl->fi->descr.port);
00797 ccn_charbuf_destroy(&temp);
00798 }
00799 }
00800 ccn_face_instance_destroy(&nfi);
00801 return;
00802 }
00803
00804 enum ccn_upcall_res
00805 incoming_interest(
00806 struct ccn_closure *selfp,
00807 enum ccn_upcall_kind kind,
00808 struct ccn_upcall_info *info)
00809 {
00810 const unsigned char *ccnb = info->interest_ccnb;
00811 struct ccn_indexbuf *comps = info->interest_comps;
00812 const unsigned char *comp0 = NULL;
00813 size_t comp0_size = 0;
00814 struct prefix_face_list_item pfl_storage = {0};
00815 struct prefix_face_list_item *pflhead = &pfl_storage;
00816 struct ccn_charbuf *uri;
00817 int port;
00818 char portstring[10];
00819 char *host;
00820 char *proto;
00821 int res;
00822
00823 if (kind == CCN_UPCALL_FINAL)
00824 return (CCN_UPCALL_RESULT_OK);
00825 if (kind != CCN_UPCALL_INTEREST)
00826 return (CCN_UPCALL_RESULT_ERR);
00827 if (comps->n < 1)
00828 return (CCN_UPCALL_RESULT_OK);
00829
00830
00831 res = ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb, comps->buf[0], comps->buf[1],
00832 &comp0, &comp0_size);
00833 if (res < 0 || comp0_size > (NS_MAXDNAME - 12))
00834 return (CCN_UPCALL_RESULT_OK);
00835 if (memchr(comp0, '.', comp0_size) == NULL)
00836 return (CCN_UPCALL_RESULT_OK);
00837
00838 host = NULL;
00839 port = 0;
00840 res = query_srv(comp0, comp0_size, &host, &port, &proto);
00841 if (res < 0) {
00842 free(host);
00843 return (CCN_UPCALL_RESULT_ERR);
00844 }
00845
00846 uri = ccn_charbuf_create();
00847 ccn_charbuf_append_string(uri, "ccnx:/");
00848 ccn_uri_append_percentescaped(uri, comp0, comp0_size);
00849 snprintf(portstring, sizeof(portstring), "%d", port);
00850
00851
00852
00853 res = process_command_tokens(pflhead, 0,
00854 "add",
00855 ccn_charbuf_as_string(uri),
00856 proto,
00857 host,
00858 portstring,
00859 NULL, NULL, NULL);
00860 if (res < 0)
00861 return (CCN_UPCALL_RESULT_ERR);
00862
00863 process_prefix_face_list_item(info->h, pflhead->next);
00864 prefix_face_list_destroy(&pflhead->next);
00865 return(CCN_UPCALL_RESULT_OK);
00866 }
00867
00868
00869 int
00870 main(int argc, char **argv)
00871 {
00872 struct ccn *h = NULL;
00873 struct ccn_charbuf *temp = NULL;
00874 const char *progname = NULL;
00875 const char *configfile = NULL;
00876 struct prefix_face_list_item pfl_storage = {0};
00877 struct prefix_face_list_item *pflhead = &pfl_storage;
00878 struct prefix_face_list_item *pfl;
00879 int dynamic = 0;
00880 struct ccn_closure interest_closure = {.p=&incoming_interest};
00881 int res;
00882 int opt;
00883
00884 initialize_global_data();
00885
00886 progname = argv[0];
00887 while ((opt = getopt(argc, argv, "hf:dv")) != -1) {
00888 switch (opt) {
00889 case 'f':
00890 configfile = optarg;
00891 break;
00892 case 'd':
00893 dynamic = 1;
00894 break;
00895 case 'v':
00896 verbose++;
00897 break;
00898 case 'h':
00899 default:
00900 usage(progname);
00901 }
00902 }
00903
00904 if (optind < argc) {
00905
00906 if (configfile != NULL) {
00907 usage(progname);
00908 }
00909
00910
00911 if (argc - optind < 2 || argc - optind > 8)
00912 usage(progname);
00913
00914 res = process_command_tokens(pflhead, 0,
00915 argv[optind],
00916 argv[optind+1],
00917 (optind + 2) < argc ? argv[optind+2] : NULL,
00918 (optind + 3) < argc ? argv[optind+3] : NULL,
00919 (optind + 4) < argc ? argv[optind+4] : NULL,
00920 (optind + 5) < argc ? argv[optind+5] : NULL,
00921 (optind + 6) < argc ? argv[optind+6] : NULL,
00922 (optind + 7) < argc ? argv[optind+7] : NULL);
00923 if (res < 0)
00924 usage(progname);
00925 }
00926
00927 if (configfile) {
00928 read_configfile(configfile, pflhead);
00929 }
00930
00931 h = ccn_create();
00932 res = ccn_connect(h, NULL);
00933 if (res < 0) {
00934 ccn_perror(h, "ccn_connect");
00935 exit(1);
00936 }
00937
00938 if (pflhead->next) {
00939 ccndid_size = get_ccndid(h, ccndid, sizeof(ccndid_storage));
00940 for (pfl = pflhead->next; pfl != NULL; pfl = pfl->next) {
00941 process_prefix_face_list_item(h, pfl);
00942 }
00943 prefix_face_list_destroy(&pflhead->next);
00944 }
00945 if (dynamic) {
00946 temp = ccn_charbuf_create();
00947 if (ccndid_size == 0) ccndid_size = get_ccndid(h, ccndid, sizeof(ccndid_storage));
00948
00949 ccn_name_init(temp);
00950 ccn_set_interest_filter_with_flags(h, temp, &interest_closure,
00951 CCN_FORW_ACTIVE | CCN_FORW_CHILD_INHERIT | CCN_FORW_LAST);
00952 ccn_charbuf_destroy(&temp);
00953 ccn_run(h, -1);
00954 }
00955 ccn_destroy(&h);
00956 exit(res < 0);
00957 }