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