示例#1
0
文件: Admin.c 项目: bringhurst/cjdns
static void handleRequestFromChild(struct Admin* admin,
                                   uint8_t buffer[MAX_API_REQUEST_SIZE],
                                   size_t amount,
                                   struct Allocator* allocator)
{
    String* txid = NULL;
    int skip = 0;

    if (!memcmp(buffer, "0123", 4)) {
        // out of band txid
        txid = &(String) { .len = 4, .bytes = (char*) buffer + 4 };
        skip = 8;
    }

    struct Reader* reader = ArrayReader_new(buffer + skip, amount - skip, allocator);
    Dict message;
    if (List_getStandardBencSerializer()->parseDictionary(reader, allocator, &message)) {
        return;
    }

    String* query = Dict_getString(&message, CJDHTConstants_QUERY);
    if (!query) {
        return;
    }

    // If they're asking for a cookie then lets give them one.
    String* cookie = BSTR("cookie");
    if (String_equals(query, cookie)) {
        Dict* d = Dict_new(allocator);
        char bytes[32];
        snprintf(bytes, 32, "%u", (uint32_t) Time_currentTimeSeconds(admin->eventBase));
        String* theCookie = &(String) { .len = strlen(bytes), .bytes = bytes };
        Dict_putString(d, cookie, theCookie, allocator);
        Admin_sendMessage(d, txid, admin);
        return;
    }

    // If this is a permitted query, make sure the cookie is right.
    String* auth = BSTR("auth");
    bool authed = false;
    if (String_equals(query, auth)) {
        if (!authValid(&message, buffer + skip, reader->bytesRead(reader), admin)) {
            Dict* d = Dict_new(allocator);
            Dict_putString(d, BSTR("error"), BSTR("Auth failed."), allocator);
            Admin_sendMessage(d, txid, admin);
            return;
        }
        query = Dict_getString(&message, BSTR("aq"));
        authed = true;
    }

    for (int i = 0; i < admin->functionCount; i++) {
        if (String_equals(query, admin->functions[i].name)
            && (authed || !admin->functions[i].needsAuth))
        {
            admin->functions[i].call(&message, admin->functions[i].context, txid);
        }
    }
    return;
}
示例#2
0
文件: MsgCore.c 项目: sssemil/cjdns
static Iface_DEFUN queryMsg(struct MsgCore_pvt* mcp,
                            Dict* content,
                            struct Address* src,
                            struct Message* msg)
{
    String* q = Dict_getStringC(content, "q");
    struct QueryHandler* qh = NULL;
    for (int i = 0; i < mcp->qh->length; i++) {
        struct QueryHandler* qhx = ArrayList_OfQueryHandlers_get(mcp->qh, i);
        Identity_check(qhx);
        if (String_equals(qhx->queryType, q)) {
            qh = qhx;
            break;
        }
    }
    if (!qh) {
        Log_debug(mcp->log, "Unhandled query type [%s]", q->bytes);
        return NULL;
    }
    if (!qh->pub.cb) {
        Log_info(mcp->log, "Query handler for [%s] not setup", q->bytes);
        return NULL;
    }
    qh->pub.cb(content, src, msg->alloc, &qh->pub);
    return NULL;
}
示例#3
0
static struct RumorMill* getRumorMill(struct Context* ctx, String* name)
{
    if (String_equals(String_CONST("externalMill"), name)) {
        return ctx->janitor->externalMill;
    } else if (String_equals(String_CONST("linkMill"), name)) {
        return ctx->janitor->linkMill;
    } else if (String_equals(String_CONST("nodeMill"), name)) {
        return ctx->janitor->nodeMill;
    } else if (String_equals(String_CONST("dhtMill"), name)) {
        return ctx->janitor->dhtMill;
    } else if (String_equals(String_CONST("splitMill"), name)) {
        return ctx->janitor->splitMill;
    } else {
        return NULL;
    }
}
示例#4
0
static void tunInterface(Dict* ifaceConf, struct Allocator* tempAlloc, struct Context* ctx)
{
    String* ifaceType = Dict_getString(ifaceConf, String_CONST("type"));
    if (!String_equals(ifaceType, String_CONST("TUNInterface"))) {
        return;
    }

    // Setup the interface.
    String* tunfd = Dict_getString(ifaceConf, String_CONST("tunfd"));
    String* device = Dict_getString(ifaceConf, String_CONST("tunDevice"));

    Dict* args = Dict_new(tempAlloc);
    if (tunfd && device) {
        Dict_putString(args, String_CONST("path"), device, tempAlloc);
        Dict_putString(args, String_CONST("type"),
                       String_new(tunfd->bytes, tempAlloc), tempAlloc);
        Dict* res = NULL;
        rpcCall0(String_CONST("FileNo_import"), args, ctx, tempAlloc, &res, false);
        if (res) {
            Dict* args = Dict_new(tempAlloc);
            int64_t* tunfd = Dict_getInt(res, String_CONST("tunfd"));
            int64_t* type = Dict_getInt(res, String_CONST("type"));
            Dict_putInt(args, String_CONST("tunfd"), *tunfd, tempAlloc);
            Dict_putInt(args, String_CONST("type"), *type, tempAlloc);
            rpcCall0(String_CONST("Core_initTunfd"), args, ctx, tempAlloc, NULL, false);
        }
    } else {
        if (device) {
            Dict_putString(args, String_CONST("desiredTunName"), device, tempAlloc);
        }
        rpcCall0(String_CONST("Core_initTunnel"), args, ctx, tempAlloc, NULL, false);
    }
}
示例#5
0
文件: CryptoAuth.c 项目: AVert/cjdns
int32_t CryptoAuth_addUser(String* password,
                           uint8_t authType,
                           String* user,
                           struct CryptoAuth* ca)
{
    struct CryptoAuth_pvt* context = Identity_check((struct CryptoAuth_pvt*) ca);
    if (authType != 1) {
        return CryptoAuth_addUser_INVALID_AUTHTYPE;
    }
    if (context->passwordCount == context->passwordCapacity) {
        // TODO(cjd): realloc password space and increase buffer.
        return CryptoAuth_addUser_OUT_OF_SPACE;
    }
    struct CryptoAuth_Auth a;
    hashPassword_sha256(&a, password);
    for (uint32_t i = 0; i < context->passwordCount; i++) {
        if (!Bits_memcmp(a.secret, context->passwords[i].secret, 32) ||
            String_equals(user, context->passwords[i].user)) {
            return CryptoAuth_addUser_DUPLICATE;
        }
    }
    a.user = String_new(user->bytes, context->allocator);
    Bits_memcpyConst(&context->passwords[context->passwordCount],
                     &a,
                     sizeof(struct CryptoAuth_Auth));
    context->passwordCount++;
    return 0;
}
示例#6
0
文件: cjdroute.c 项目: avary/cjdns
static int getcmds(Dict* config)
{
    uint8_t privateKey[32];
    struct Address addr;
    parsePrivateKey(config, &addr, privateKey);

    uint8_t myIp[40];
    Address_printIp(myIp, &addr);

    Dict* router = Dict_getDict(config, BSTR("router"));
    Dict* iface = Dict_getDict(router, BSTR("interface"));
    String* type = Dict_getString(iface, BSTR("type"));
    String* tunDevice = Dict_getString(iface, BSTR("tunDevice"));
    if (!String_equals(type, BSTR("TUNInterface"))) {
        fprintf(stderr, "router.interface.type is not recognized.\n");
        return -1;
    }
    char* tunDev = tunDevice ? tunDevice->bytes : "tun0";
    if (strrchr(tunDev, '/') != NULL) {
        tunDev = strrchr(tunDev, '/') + 1;
    }

    printf("#!/bin/bash\n"
           "# Run these commands as root now and every time the system is rebooted\n"
           "# in order to get the interfaces setup properly.\n\n");
    printf("/sbin/ip addr add %s dev %s\n", myIp, tunDev);
    printf("/sbin/ip -6 route add fc00::/8 dev %s\n", tunDev);
    printf("/sbin/ip link set %s up\n", tunDev);

    return 0;
}
示例#7
0
static void rpcCall0(String* function,
                     Dict* args,
                     struct Context* ctx,
                     struct Allocator* alloc,
                     bool exitIfError)
{
    struct AdminClient_Result* res = AdminClient_rpcCall(function, args, ctx->client, alloc);
    if (res->err) {
        Log_critical(ctx->logger,
                      "Failed to make function call [%s], error: [%s]",
                      AdminClient_errorString(res->err),
                      function->bytes);
        die(res, ctx, alloc);
    }
    String* error = Dict_getString(res->responseDict, String_CONST("error"));
    if (error && !String_equals(error, String_CONST("none"))) {
        if (exitIfError) {
            Log_critical(ctx->logger,
                         "Got error [%s] calling [%s]",
                         error->bytes,
                         function->bytes);
            die(res, ctx, alloc);
        }
        Log_warn(ctx->logger, "Got error [%s] calling [%s], ignoring.",
                 error->bytes, function->bytes);
    }
}
示例#8
0
/* Tests whether v starts with w. */
static boolean VectorString_startsWith (const VectorString* v, const VectorString* w)
{
  uintL n = VectorString_length(w);
  if (VectorString_length(v) >= n) {
    uintL i;
    for (i = 0; i < n; i++)
      if (!String_equals(VectorString_element(v,i),VectorString_element(w,i)))
        return FALSE;
    return TRUE;
  }
  return FALSE;
}
示例#9
0
static int tryPing(struct Allocator* tempAlloc, struct Context* ctx)
{
    Dict* resp = NULL;
    Dict* d = Dict_new(tempAlloc);
    rpcCall0(String_CONST("ping"), d, ctx, tempAlloc, &resp, false);
    if (!resp) { return -1; }
    String* q = Dict_getString(resp, String_CONST("q"));
    if (String_equals(q, String_CONST("pong"))) {
        return true;
    }
    return false;
}
示例#10
0
文件: cjdroute.c 项目: Ralith/cjdns
static void registerRouter(Dict* config, uint8_t myPubKey[32], struct Context* context)
{
    Dict* iface = Dict_getDict(config, BSTR("interface"));
    if (String_equals(Dict_getString(iface, BSTR("type")), BSTR("TUNInterface"))) {
        String* tunPath = Dict_getString(iface, BSTR("tunDevice"));
        context->routerIf = TUNInterface_new(tunPath, context->base, context->allocator);
    }
    context->routerModule = RouterModule_register(context->registry,
                                                  context->allocator,
                                                  myPubKey,
                                                  context->base,
                                                  context->logger,
                                                  context->admin);
}
示例#11
0
文件: string.c 项目: qc1iu/dog-comp
T String_new(T x)
{
    int len;
    char* s;

    len = strlen(x);
    Mem_newSize(s, len+1);
    strcpy(s, x);

    if (String_equals(s, x))
      return s;

    ERROR("string_new err!");
}
示例#12
0
文件: CryptoAuth.c 项目: cmotc/cjdns
int CryptoAuth_addUser_ipv6(String* password,
                            String* login,
                            uint8_t ipv6[16],
                            struct CryptoAuth* cryptoAuth)
{
    struct CryptoAuth_pvt* ca = Identity_check((struct CryptoAuth_pvt*) cryptoAuth);

    struct Allocator* alloc = Allocator_child(ca->allocator);
    struct CryptoAuth_User* user = Allocator_calloc(alloc, sizeof(struct CryptoAuth_User), 1);
    user->alloc = alloc;
    Identity_set(user);

    if (!login) {
        int i = 0;
        for (struct CryptoAuth_User* u = ca->users; u; u = u->next) { i++; }
        user->login = login = String_printf(alloc, "Anon #%d", i);
    } else {
        user->login = String_clone(login, alloc);
    }

    union CryptoHeader_Challenge ac;
    // Users specified with a login field might want to use authType 1 still.
    hashPassword(user->secret, &ac, login, password, 2);
    Bits_memcpyConst(user->userNameHash, ac.bytes, CryptoHeader_Challenge_KEYSIZE);
    hashPassword(user->secret, &ac, NULL, password, 1);
    Bits_memcpyConst(user->passwordHash, ac.bytes, CryptoHeader_Challenge_KEYSIZE);

    for (struct CryptoAuth_User* u = ca->users; u; u = u->next) {
        if (Bits_memcmp(user->secret, u->secret, 32)) {
        } else if (!login) {
        } else if (String_equals(login, u->login)) {
            Allocator_free(alloc);
            return CryptoAuth_addUser_DUPLICATE;
        }
    }

    if (ipv6) {
        Bits_memcpyConst(user->restrictedToip6, ipv6, 16);
    }

    // Add the user to the *end* of the list
    for (struct CryptoAuth_User** up = &ca->users; ; up = &(*up)->next) {
        if (!*up) {
            *up = user;
            break;
        }
    }

    return 0;
}
示例#13
0
static int rpcCall0(String* function,
                    Dict* args,
                    struct Context* ctx,
                    struct Allocator* alloc,
                    Dict** resultP,
                    bool exitIfError)
{
    ctx->currentReqAlloc = Allocator_child(alloc);
    ctx->currentResult = NULL;
    struct AdminClient_Promise* promise = AdminClient_rpcCall(function, args, ctx->client, alloc);
    promise->callback = rpcCallback;
    promise->userData = ctx;

    EventBase_beginLoop(ctx->base);

    struct AdminClient_Result* res = ctx->currentResult;
    Assert_true(res);

    if (res->err) {
        Log_critical(ctx->logger,
                      "Failed to make function call [%s], error: [%s]",
                      AdminClient_errorString(res->err),
                      function->bytes);
        die(res, ctx, alloc);
    }
    String* error = Dict_getString(res->responseDict, String_CONST("error"));
    int ret = 0;
    if (error && !String_equals(error, String_CONST("none"))) {
        if (exitIfError) {
            Log_critical(ctx->logger,
                         "Got error [%s] calling [%s]",
                         error->bytes,
                         function->bytes);
            die(res, ctx, alloc);
        }
        Log_warn(ctx->logger, "Got error [%s] calling [%s], ignoring.",
                 error->bytes, function->bytes);
        ret = 1;
    }

    if (resultP) {
        *resultP = res->responseDict;
    } else {
        Allocator_free(ctx->currentReqAlloc);
    }
    ctx->currentReqAlloc = NULL;

    return ret;
}
FileFragmentNode *FileFragmentList_findFile(FileFragmentList *fileFragmentList, const String fileName)
{
  FileFragmentNode *fileFragmentNode;

  assert(fileFragmentList != NULL);
  assert(fileName != NULL);

  fileFragmentNode = fileFragmentList->head;
  while ((fileFragmentNode != NULL) && (!String_equals(fileFragmentNode->fileName,fileName)))
  {
    fileFragmentNode = fileFragmentNode->next;
  }

  return fileFragmentNode;
}
示例#15
0
FragmentNode *FragmentList_find(FragmentList *fragmentList, const String name)
{
  FragmentNode *fragmentNode;

  assert(fragmentList != NULL);
  assert(name != NULL);

  fragmentNode = fragmentList->head;
  while ((fragmentNode != NULL) && (!String_equals(fragmentNode->name,name)))
  {
    fragmentNode = fragmentNode->next;
  }

  return fragmentNode;
}
示例#16
0
static void testGetUsers()
{
    struct Allocator* allocator = MallocAllocator_new(1<<20);
    struct EventBase* base = EventBase_new(allocator);
    struct CryptoAuth* ca =
        CryptoAuth_new(allocator, NULL, base, NULL, evilRandom(allocator, NULL));
    List* users = NULL;

    users = CryptoAuth_getUsers(ca, allocator);
    Assert_true(List_size(users) == 0);

    CryptoAuth_addUser(String_CONST("pass1"), String_CONST("user1"), ca);
    users = CryptoAuth_getUsers(ca, allocator);
    Assert_true(List_size(users) == 1);
    Assert_true(String_equals(String_CONST("user1"), List_getString(users,0)));

    CryptoAuth_addUser(String_CONST("pass2"), String_CONST("user2"), ca);
    users = CryptoAuth_getUsers(ca, allocator);
    Assert_true(List_size(users) == 2);
    Assert_true(String_equals(String_CONST("user2"),List_getString(users,0)));
    Assert_true(String_equals(String_CONST("user1"),List_getString(users,1)));

    Allocator_free(allocator);
}
示例#17
0
static void tunInterface(Dict* ifaceConf, struct Allocator* tempAlloc, struct Context* ctx)
{
    String* ifaceType = Dict_getString(ifaceConf, String_CONST("type"));
    if (!String_equals(ifaceType, String_CONST("TUNInterface"))) {
        return;
    }

    // Setup the interface.
    String* device = Dict_getString(ifaceConf, String_CONST("tunDevice"));

    Dict* args = Dict_new(tempAlloc);
    if (device) {
        Dict_putString(args, String_CONST("desiredTunName"), device, tempAlloc);
    }
    rpcCall0(String_CONST("Core_initTunnel"), args, ctx, tempAlloc, false);
}
示例#18
0
static const VectorString* modulo_current_condition (const VectorString* condition)
{
  /* Quick and dirty: Just remove the start segment:
   condition[0]==current_condition[0], ... condition[n]==current_condition[n]. */
  VectorString* current = current_condition();
  uintL i;
  for (i = 0; i < VectorString_length(current) && i < VectorString_length(condition); i++)
    if (!String_equals(VectorString_element(current,i),VectorString_element(condition,i)))
      break;
  if (i == 0)
    return condition;
  else {
    VectorString* new_condition = make_VectorString();
    for (; i < VectorString_length(condition); i++)
      VectorString_add(new_condition,VectorString_element(condition,i));
    return new_condition;
  }
}
示例#19
0
static void security(List* securityConf, struct Allocator* tempAlloc, struct Context* ctx)
{
    bool noFiles = false;
    for (int i = 0; i < List_size(securityConf); i++) {
        if (String_equals(String_CONST("nofiles"), List_getString(securityConf, i))) {
            noFiles = true;
        } else {
            Dict* userDict = List_getDict(securityConf, i);
            String* userName = Dict_getString(userDict, String_CONST("setuser"));
            if (userName) {
                Dict d = Dict_CONST(String_CONST("user"), String_OBJ(userName), NULL);
                // If this call returns an error, it is ok.
                rpcCall0(String_CONST("Security_setUser"), &d, ctx, tempAlloc, false);
            }
        }
    }
    if (noFiles) {
        Dict d = NULL;
        rpcCall(String_CONST("Security_noFiles"), &d, ctx, tempAlloc);
    }
}
示例#20
0
static void rpcCall(String* function, Dict* args, struct Context* ctx, struct Allocator* alloc)
{
    struct AdminClient_Result* res = AdminClient_rpcCall(function, args, ctx->client, alloc);
    if (res->err) {
        Log_critical2(ctx->logger,
                      "Failed to make function call [%s], error: [%s]",
                      AdminClient_errorString(res->err),
                      function->bytes);
        showMsg(res, ctx);
        exit(-1);
    }
    String* error = Dict_getString(res->responseDict, String_CONST("error"));
    if (error && !String_equals(error, String_CONST("none"))) {
        Log_critical2(ctx->logger,
                      "Router responses with error: [%s]\nCalling function: [%s]",
                      error->bytes,
                      function->bytes);
        showMsg(res, ctx);
        exit(-1);
    }
}
示例#21
0
文件: cjdroute.c 项目: Ralith/cjdns
static void security(List* config, struct Log* logger, struct ExceptionHandler* eh)
{
    if (!config) {
        return;
    }
    bool nofiles = false;
    for (int i = 0; i < List_size(config); i++) {
        String* s = List_getString(config, i);
        if (s && String_equals(s, BSTR("nofiles"))) {
            nofiles = true;
        }
    }
    char* user = setUser(config);
    if (user) {
        Log_info1(logger, "Changing user to [%s]\n", user);
        Security_setUser(user, logger, eh);
    }
    if (nofiles) {
        Log_info(logger, "Setting max open files to zero.\n");
        Security_noFiles(eh);
    }
}
示例#22
0
文件: cjdroute.c 项目: Ralith/cjdns
static int getcmds(Dict* config)
{
    uint8_t privateKey[32];
    struct Address addr;
    parsePrivateKey(config, &addr, privateKey);

    uint8_t myIp[40];
    Address_printIp(myIp, &addr);

    Dict* router = Dict_getDict(config, BSTR("router"));
    Dict* iface = Dict_getDict(router, BSTR("interface"));
    String* type = Dict_getString(iface, BSTR("type"));
    String* tunDevice = Dict_getString(iface, BSTR("tunDevice"));
    if (!String_equals(type, BSTR("TUNInterface"))) {
        fprintf(stderr, "router.interface.type is not recognized.\n");
        return -1;
    }
    char *tunDev = (tunDevice) ? tunDevice->bytes : DEFAULT_TUN_DEV;
    if (strrchr(tunDev, '/') != NULL) {
        tunDev = strrchr(tunDev, '/') + 1;
    }

    printf("#!/bin/bash\n"
           "# Run these commands immediately after cjdns is initialized\n"
           "# in order to get the interfaces setup properly.\n"
           "# If you are using persistent tunnels (see README.md),\n"
           "# you may run them once every time the system starts up.\n");

#ifdef __APPLE__
    printf("ifconfig %s inet6 %s\n", tunDev, myIp);
    printf("route -n add -inet6 fc00::/8 -interface %s\n", tunDev);
#else
    printf("/sbin/ip addr add %s dev %s\n", myIp, tunDev);
    printf("/sbin/ip -6 route add fc00::/8 dev %s\n", tunDev);
    printf("/sbin/ip link set %s up\n", tunDev);
#endif /* __APPLE__ */

    return 0;
}
示例#23
0
文件: CryptoAuth.c 项目: cmotc/cjdns
void CryptoAuth_setAuth(const String* password,
                        const String* login,
                        struct CryptoAuth_Session* caSession)
{
    struct CryptoAuth_Session_pvt* session =
        Identity_check((struct CryptoAuth_Session_pvt*)caSession);

    if (!password && (session->password || session->authType)) {
        session->password = NULL;
        session->authType = 0;
    } else if (!session->password || !String_equals(session->password, password)) {
        session->password = String_clone(password, session->alloc);
        session->authType = 1;
        if (login) {
            session->authType = 2;
            session->login = String_clone(login, session->alloc);
        }
    } else {
        return;
    }
    reset(session);
}
示例#24
0
文件: CryptoAuth.c 项目: cmotc/cjdns
int CryptoAuth_removeUsers(struct CryptoAuth* context, String* login)
{
    struct CryptoAuth_pvt* ca = Identity_check((struct CryptoAuth_pvt*) context);

    int count = 0;
    struct CryptoAuth_User** up = &ca->users;
    struct CryptoAuth_User* u = *up;
    while ((u = *up)) {
        if (!login || String_equals(login, u->login)) {
            *up = u->next;
            Allocator_free(u->alloc);
            count++;
        } else {
            up = &u->next;
        }
    }

    if (!login) {
        Log_debug(ca->logger, "Flushing [%d] users", count);
    } else {
        Log_debug(ca->logger, "Removing [%d] user(s) identified by [%s]", count, login->bytes);
    }
    return count;
}
示例#25
0
文件: CryptoAuth.c 项目: AVert/cjdns
int CryptoAuth_removeUsers(struct CryptoAuth* context, String* user)
{
    struct CryptoAuth_pvt* ctx = Identity_check((struct CryptoAuth_pvt*) context);
    if (!user) {
        int count = ctx->passwordCount;
        Log_debug(ctx->logger, "Flushing [%d] users", count);
        ctx->passwordCount = 0;
        return count;
    }
    int count = 0;
    int i = 0;
    while (i < (int)ctx->passwordCount) {
        if (String_equals(ctx->passwords[i].user, user)) {
            Bits_memcpyConst(&ctx->passwords[i],
                             &ctx->passwords[ctx->passwordCount--],
                             sizeof(struct CryptoAuth_Auth));
            count++;
        } else {
            i++;
        }
    }
    Log_debug(ctx->logger, "Removing [%d] user(s) identified by [%s]", count, user->bytes);
    return count;
}
示例#26
0
文件: Admin.c 项目: sjmackenzie/cjdns
static void handleRequestFromChild(struct Admin* admin,
                                   union Admin_TxidPrefix* txid_prefix,
                                   Dict* message,
                                   uint8_t* buffer,
                                   size_t amount,
                                   struct Allocator* allocator)
{
    String* query = Dict_getString(message, CJDHTConstants_QUERY);
    if (!query) {
        Log_info(admin->logger,
                 "Got a non-query from admin interface on channel [%u].",
                 admin->messageHeader.channelNum);
        adminChannelClose(admin, admin->messageHeader.channelNum);
        return;
    }

    // txid becomes the user supplied txid combined with the inter-process txid.
    String* userTxid = Dict_getString(message, TXID);
    uint32_t txidlen = ((userTxid) ? userTxid->len : 0) + Admin_TxidPrefix_SIZE;
    String* txid = String_newBinary(NULL, txidlen, allocator);
    Bits_memcpyConst(txid->bytes, txid_prefix->raw, Admin_TxidPrefix_SIZE);
    if (userTxid) {
        Bits_memcpy(txid->bytes + Admin_TxidPrefix_SIZE, userTxid->bytes, userTxid->len);
    }

    // If they're asking for a cookie then lets give them one.
    String* cookie = String_CONST("cookie");
    if (String_equals(query, cookie)) {
        Dict* d = Dict_new(allocator);
        char bytes[32];
        snprintf(bytes, 32, "%u", (uint32_t) Time_currentTimeSeconds(admin->eventBase));
        String* theCookie = &(String) { .len = strlen(bytes), .bytes = bytes };
        Dict_putString(d, cookie, theCookie, allocator);
        Admin_sendMessage(d, txid, admin);
        return;
    }

    // If this is a permitted query, make sure the cookie is right.
    String* auth = String_CONST("auth");
    bool authed = false;
    if (String_equals(query, auth)) {
        if (!authValid(message, buffer, amount, admin)) {
            Dict* d = Dict_new(allocator);
            Dict_putString(d, String_CONST("error"), String_CONST("Auth failed."), allocator);
            Admin_sendMessage(d, txid, admin);
            return;
        }
        query = Dict_getString(message, String_CONST("aq"));
        authed = true;
    }

    Dict* args = Dict_getDict(message, String_CONST("args"));
    bool noFunctionsCalled = true;
    for (int i = 0; i < admin->functionCount; i++) {
        if (String_equals(query, admin->functions[i].name)
            && (authed || !admin->functions[i].needsAuth))
        {
            if (checkArgs(args, &admin->functions[i], txid, admin)) {
                admin->functions[i].call(args, admin->functions[i].context, txid);
            }
            noFunctionsCalled = false;
        }
    }

    if (noFunctionsCalled) {
        Dict* d = Dict_new(allocator);
        Dict_putString(d,
                       String_CONST("error"),
                       String_CONST("No functions matched your request."),
                       allocator);
        Dict* functions = Dict_new(allocator);
        for (int i = 0; i < admin->functionCount; i++) {
            Dict_putDict(functions, admin->functions[i].name, admin->functions[i].args, allocator);
        }
        if (functions) {
            Dict_putDict(d, String_CONST("availableFunctions"), functions, allocator);
        }
        Admin_sendMessage(d, txid, admin);
        return;
    }

    return;
}
示例#27
0
// incoming message from network, pointing to the beginning of the switch header.
static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
{
    struct SwitchPinger* ctx = Identity_check((struct SwitchPinger*) iface->receiverContext);
    struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
    ctx->incomingLabel = Endian_bigEndianToHost64(switchHeader->label_be);
    ctx->incomingVersion = 0;
    Message_shift(msg, -SwitchHeader_SIZE, NULL);

    uint32_t handle = Message_pop32(msg, NULL);
    #ifdef Version_7_COMPAT
    if (handle != 0xffffffff) {
        Message_push32(msg, handle, NULL);
        handle = 0xffffffff;
        Assert_true(SwitchHeader_isV7Ctrl(switchHeader));
    }
    #endif
    Assert_true(handle == 0xffffffff);

    struct Control* ctrl = (struct Control*) msg->bytes;
    if (ctrl->type_be == Control_PONG_be) {
        Message_shift(msg, -Control_HEADER_SIZE, NULL);
        ctx->error = Error_NONE;
        if (msg->length >= Control_Pong_MIN_SIZE) {
            struct Control_Ping* pongHeader = (struct Control_Ping*) msg->bytes;
            ctx->incomingVersion = Endian_bigEndianToHost32(pongHeader->version_be);
            if (pongHeader->magic != Control_Pong_MAGIC) {
                Log_debug(ctx->logger, "dropped invalid switch pong");
                return Error_INVALID;
            }
            Message_shift(msg, -Control_Pong_HEADER_SIZE, NULL);
        } else {
            Log_debug(ctx->logger, "got runt pong message, length: [%d]", msg->length);
            return Error_INVALID;
        }

    } else if (ctrl->type_be == Control_KEYPONG_be) {
        Message_shift(msg, -Control_HEADER_SIZE, NULL);
        ctx->error = Error_NONE;
        if (msg->length >= Control_KeyPong_HEADER_SIZE && msg->length <= Control_KeyPong_MAX_SIZE) {
            struct Control_KeyPing* pongHeader = (struct Control_KeyPing*) msg->bytes;
            ctx->incomingVersion = Endian_bigEndianToHost32(pongHeader->version_be);
            if (pongHeader->magic != Control_KeyPong_MAGIC) {
                Log_debug(ctx->logger, "dropped invalid switch key-pong");
                return Error_INVALID;
            }
            Bits_memcpyConst(ctx->incomingKey, pongHeader->key, 32);
            Message_shift(msg, -Control_KeyPong_HEADER_SIZE, NULL);
        } else if (msg->length > Control_KeyPong_MAX_SIZE) {
            Log_debug(ctx->logger, "got overlong key-pong message, length: [%d]", msg->length);
            return Error_INVALID;
        } else {
            Log_debug(ctx->logger, "got runt key-pong message, length: [%d]", msg->length);
            return Error_INVALID;
        }

    } else if (ctrl->type_be == Control_ERROR_be) {
        Message_shift(msg, -Control_HEADER_SIZE, NULL);
        Assert_true((uint8_t*)&ctrl->content.error.errorType_be == msg->bytes);
        if (msg->length < (Control_Error_HEADER_SIZE + SwitchHeader_SIZE + Control_HEADER_SIZE)) {
            Log_debug(ctx->logger, "runt error packet");
            return Error_NONE;
        }

        ctx->error = Message_pop32(msg, NULL);
        Message_push32(msg, 0, NULL);

        Message_shift(msg, -(Control_Error_HEADER_SIZE + SwitchHeader_SIZE), NULL);

        struct Control* origCtrl = (struct Control*) msg->bytes;

        Log_debug(ctx->logger, "error [%s] was caused by our [%s]",
                  Error_strerror(ctx->error),
                  Control_typeString(origCtrl->type_be));

        int shift;
        if (origCtrl->type_be == Control_PING_be) {
            shift = -(Control_HEADER_SIZE + Control_Ping_HEADER_SIZE);
        } else if (origCtrl->type_be == Control_KEYPING_be) {
            shift = -(Control_HEADER_SIZE + Control_KeyPing_HEADER_SIZE);
        } else {
            Assert_failure("problem in Ducttape.c");
        }
        if (msg->length < -shift) {
            Log_debug(ctx->logger, "runt error packet");
        }
        Message_shift(msg, shift, NULL);

    } else {
        // If it gets here then Ducttape.c is failing.
        Assert_true(false);
    }

    String* msgStr = &(String) { .bytes = (char*) msg->bytes, .len = msg->length };
    Pinger_pongReceived(msgStr, ctx->pinger);
    Bits_memset(ctx->incomingKey, 0, 32);
    return Error_NONE;
}

static void onPingResponse(String* data, uint32_t milliseconds, void* vping)
{
    struct Ping* p = Identity_check((struct Ping*) vping);
    enum SwitchPinger_Result err = SwitchPinger_Result_OK;
    uint64_t label = p->context->incomingLabel;
    if (data) {
        if (label != p->label) {
            err = SwitchPinger_Result_LABEL_MISMATCH;
        } else if ((p->data || data->len > 0) && !String_equals(data, p->data)) {
            err = SwitchPinger_Result_WRONG_DATA;
        } else if (p->context->error == Error_LOOP_ROUTE) {
            err = SwitchPinger_Result_LOOP_ROUTE;
        } else if (p->context->error) {
            err = SwitchPinger_Result_ERROR_RESPONSE;
        }
    } else {
        err = SwitchPinger_Result_TIMEOUT;
    }

    uint32_t version = p->context->incomingVersion;
    struct SwitchPinger_Response* resp =
        Allocator_calloc(p->pub.pingAlloc, sizeof(struct SwitchPinger_Response), 1);
    resp->version = p->context->incomingVersion;
    resp->res = err;
    resp->label = label;
    resp->data = data;
    resp->milliseconds = milliseconds;
    resp->version = version;
    Bits_memcpyConst(resp->key, p->context->incomingKey, 32);
    resp->ping = &p->pub;
    p->onResponse(resp, p->pub.onResponseContext);
}

static void sendPing(String* data, void* sendPingContext)
{
    struct Ping* p = Identity_check((struct Ping*) sendPingContext);

    struct Message* msg = Message_new(0, data->len + 512, p->pub.pingAlloc);

    while (((uintptr_t)msg->bytes - data->len) % 4) {
        Message_push8(msg, 0, NULL);
    }
    msg->length = 0;

    Message_push(msg, data->bytes, data->len, NULL);
    Assert_true(!((uintptr_t)msg->bytes % 4) && "alignment fault");

    if (p->pub.keyPing) {
        Message_shift(msg, Control_KeyPing_HEADER_SIZE, NULL);
        struct Control_KeyPing* keyPingHeader = (struct Control_KeyPing*) msg->bytes;
        keyPingHeader->magic = Control_KeyPing_MAGIC;
        keyPingHeader->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL);
        Bits_memcpyConst(keyPingHeader->key, p->context->myAddr->key, 32);
    } else {
        Message_shift(msg, Control_Ping_HEADER_SIZE, NULL);
        struct Control_Ping* pingHeader = (struct Control_Ping*) msg->bytes;
        pingHeader->magic = Control_Ping_MAGIC;
        pingHeader->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL);
    }

    Message_shift(msg, Control_HEADER_SIZE, NULL);
    struct Control* ctrl = (struct Control*) msg->bytes;
    ctrl->checksum_be = 0;
    ctrl->type_be = (p->pub.keyPing) ? Control_KEYPING_be : Control_PING_be;
    ctrl->checksum_be = Checksum_engine(msg->bytes, msg->length);

    #ifdef Version_7_COMPAT
        if (0) {
    #endif
    Message_push32(msg, 0xffffffff, NULL);
    #ifdef Version_7_COMPAT
        }
    #endif

    Message_shift(msg, SwitchHeader_SIZE, NULL);
    struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
    switchHeader->label_be = Endian_hostToBigEndian64(p->label);

    SwitchHeader_setVersion(switchHeader, SwitchHeader_CURRENT_VERSION);
    SwitchHeader_setPenalty(switchHeader, 0);
    SwitchHeader_setCongestion(switchHeader, 0);

    #ifdef Version_7_COMPAT
        // v7 detects ctrl packets by the bit which has been
        // re-appropriated for suppression of errors.
        switchHeader->congestAndSuppressErrors = 1;
        SwitchHeader_setVersion(switchHeader, 0);
    #endif

    p->context->iface->sendMessage(msg, p->context->iface);
}

static String* RESULT_STRING_OK =             String_CONST_SO("pong");
static String* RESULT_STRING_LABEL_MISMATCH = String_CONST_SO("diff_label");
static String* RESULT_STRING_WRONG_DATA =     String_CONST_SO("diff_data");
static String* RESULT_STRING_ERROR_RESPONSE = String_CONST_SO("err_switch");
static String* RESULT_STRING_TIMEOUT =        String_CONST_SO("timeout");
static String* RESULT_STRING_UNKNOWN =        String_CONST_SO("err_unknown");
static String* RESULT_STRING_LOOP =           String_CONST_SO("err_loop");

String* SwitchPinger_resultString(enum SwitchPinger_Result result)
{
    switch (result) {
        case SwitchPinger_Result_OK:
            return RESULT_STRING_OK;

        case SwitchPinger_Result_LABEL_MISMATCH:
            return RESULT_STRING_LABEL_MISMATCH;

        case SwitchPinger_Result_WRONG_DATA:
            return RESULT_STRING_WRONG_DATA;

        case SwitchPinger_Result_ERROR_RESPONSE:
            return RESULT_STRING_ERROR_RESPONSE;

        case SwitchPinger_Result_TIMEOUT:
            return RESULT_STRING_TIMEOUT;

        case SwitchPinger_Result_LOOP_ROUTE:
            return RESULT_STRING_LOOP;

        default:
            return RESULT_STRING_UNKNOWN;
    };
}

static int onPingFree(struct Allocator_OnFreeJob* job)
{
    struct Ping* ping = Identity_check((struct Ping*)job->userData);
    struct SwitchPinger* ctx = Identity_check(ping->context);
    ctx->outstandingPings--;
    Assert_true(ctx->outstandingPings >= 0);
    return 0;
}

struct SwitchPinger_Ping* SwitchPinger_newPing(uint64_t label,
                                               String* data,
                                               uint32_t timeoutMilliseconds,
                                               SwitchPinger_ResponseCallback onResponse,
                                               struct Allocator* alloc,
                                               struct SwitchPinger* ctx)
{
    if (data && data->len > Control_Ping_MAX_SIZE) {
        return NULL;
    }

    if (ctx->outstandingPings > ctx->maxConcurrentPings) {
        Log_debug(ctx->logger, "Skipping switch ping because there are already [%d] outstanding",
                  ctx->outstandingPings);
        return NULL;
    }

    struct Pinger_Ping* pp =
        Pinger_newPing(data, onPingResponse, sendPing, timeoutMilliseconds, alloc, ctx->pinger);

    struct Ping* ping = Allocator_clone(pp->pingAlloc, (&(struct Ping) {
        .pub = {
            .pingAlloc = pp->pingAlloc
        },
        .label = label,
        .data = String_clone(data, pp->pingAlloc),
        .context = ctx,
        .onResponse = onResponse,
        .pingerPing = pp
    }));
示例#28
0
int main(int argc, char** argv)
{
    #ifdef Log_KEYS
        fprintf(stderr, "Log_LEVEL = KEYS, EXPECT TO SEE PRIVATE KEYS IN YOUR LOGS!\n");
    #endif
    Crypto_init();
    Assert_true(argc > 0);

    if (argc == 2) {
        // one argument
        if (strcmp(argv[1], "--help") == 0) {
            return usage(argv[0]);
        } else if (strcmp(argv[1], "--genconf") == 0) {
            return genconf();
        } else if (strcmp(argv[1], "--pidfile") == 0) {
            // Performed after reading the configuration
        } else if (strcmp(argv[1], "--reconf") == 0) {
            // Performed after reading the configuration
        } else if (strcmp(argv[1], "--bench") == 0) {
            return benchmark();
        } else if (strcmp(argv[1], "--version") == 0) {
            printf("Version ID: %s\n", RouterModule_gitVersion());
            return 0;
        } else {
            fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[1]);
            fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
            return -1;
        }
    } else if (argc >  2) {
        // more than one argument?
        fprintf(stderr, "%s: too many arguments\n", argv[0]);
        fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
        return -1;
    }

    if (isatty(STDIN_FILENO)) {
        // We were started from a terminal
        // The chances an user wants to type in a configuration
        // bij hand are pretty slim so we show him the usage
        return usage(argv[0]);
    } else {
        // We assume stdin is a configuration file and that we should
        // start routing
    }

    struct event_base* eventBase = event_base_new();

    // Allow it to allocate 4MB
    struct Allocator* allocator = MallocAllocator_new(1<<22);
    struct Reader* reader = FileReader_new(stdin, allocator);
    Dict config;
    if (JsonBencSerializer_get()->parseDictionary(reader, allocator, &config)) {
        fprintf(stderr, "Failed to parse configuration.\n");
        return -1;
    }

    // Logging.
    struct Writer* logwriter = FileWriter_new(stdout, allocator);
    struct Log* logger = &(struct Log) { .writer = logwriter };


    // pid file
    String* pidFile = Dict_getString(&config, String_CONST("pidFile"));
    if (pidFile) {
        if (argc == 2 && strcmp(argv[1], "--pidfile") == 0) {
            printf("%s", pidFile->bytes);
            return 0;
        }
        Log_info(logger, "Writing pid of process to [%s].\n", pidFile->bytes);
        FILE* pf = fopen(pidFile->bytes, "w");
        if (!pf) {
            Log_critical(logger,
                          "Failed to open pid file [%s] for writing, errno=%d\n",
                          pidFile->bytes,
                          errno);
            return -1;
        }
        fprintf(pf, "%d", (int) getpid());
        fclose(pf);
    }

    // re-configure
    if (argc == 2 && strcmp(argv[1], "--reconf") == 0) {
        reconf(eventBase, &config, logger, allocator);
        return 0;
    }

    // ca, needed for admin.
    struct Address myAddr;
    uint8_t privateKey[32];
    parsePrivateKey(&config, &myAddr, privateKey);
    struct CryptoAuth* cryptoAuth =
        CryptoAuth_new(&config, allocator, privateKey, eventBase, logger);

    // Admin
    char* user = setUser(Dict_getList(&config, String_CONST("security")));
    struct Admin* admin = newAdmin(&config, user, logger, eventBase, allocator);

    struct SwitchCore* switchCore = SwitchCore_new(logger, allocator);
    struct DHTModuleRegistry* registry = DHTModuleRegistry_new(allocator);
    ReplyModule_register(registry, allocator);

    // Router
    struct Interface* routerIf = NULL;
    Dict* routerConf = Dict_getDict(&config, String_CONST("router"));
    Dict* iface = Dict_getDict(routerConf, String_CONST("interface"));
    if (String_equals(Dict_getString(iface, String_CONST("type")), String_CONST("TUNInterface"))) {
        String* ifName = Dict_getString(iface, String_CONST("tunDevice"));

        char assignedTunName[TUNConfigurator_IFNAMSIZ];
        void* tunPtr = TUNConfigurator_initTun(((ifName) ? ifName->bytes : NULL),
                                               assignedTunName,
                                               logger,
                                               AbortHandler_INSTANCE);
        struct Jmp jmp;
        Jmp_try(jmp) {
            TUNConfigurator_setIpAddress(
                assignedTunName, myAddr.ip6.bytes, 8, logger, &jmp.handler);
        } Jmp_catch {
            Log_warn(logger, "Unable to configure ip address [%s]", jmp.message);
        }

        struct TUNInterface* tun = TUNInterface_new(tunPtr, eventBase, allocator);
        routerIf = &tun->iface;

    }
示例#29
0
Errors Command_compare(StringList                      *archiveFileNameList,
                       EntryList                       *includeEntryList,
                       PatternList                     *excludePatternList,
                       JobOptions                      *jobOptions,
                       ArchiveGetCryptPasswordFunction archiveGetCryptPasswordFunction,
                       void                            *archiveGetCryptPasswordUserData
                      )
{
  byte              *archiveBuffer,*buffer;
  FragmentList      fragmentList;
  String            archiveFileName;
  Errors            failError;
  Errors            error;
  ArchiveInfo       archiveInfo;
  ArchiveFileInfo   archiveFileInfo;
  ArchiveEntryTypes archiveEntryType;
  FragmentNode      *fragmentNode;

  assert(archiveFileNameList != NULL);
  assert(includeEntryList != NULL);
  assert(excludePatternList != NULL);
  assert(jobOptions != NULL);

  /* allocate resources */
  archiveBuffer = (byte*)malloc(BUFFER_SIZE);
  if (archiveBuffer == NULL)
  {
    HALT_INSUFFICIENT_MEMORY();
  }
  buffer = malloc(BUFFER_SIZE);
  if (buffer == NULL)
  {
    free(archiveBuffer);
    HALT_INSUFFICIENT_MEMORY();
  }
  FragmentList_init(&fragmentList);
  archiveFileName = String_new();

  failError = ERROR_NONE;
  while (   !StringList_empty(archiveFileNameList)
         && (failError == ERROR_NONE)
        )
  {
    StringList_getFirst(archiveFileNameList,archiveFileName);
    printInfo(1,"Comparing archive '%s':\n",String_cString(archiveFileName));

    /* open archive */
    error = Archive_open(&archiveInfo,
                         archiveFileName,
                         jobOptions,
                         archiveGetCryptPasswordFunction,
                         archiveGetCryptPasswordUserData
                        );
    if (error != ERROR_NONE)
    {
      printError("Cannot open archive file '%s' (error: %s)!\n",
                 String_cString(archiveFileName),
                 Errors_getText(error)
                );
      if (failError == ERROR_NONE) failError = error;
      continue;
    }

    /* read files */
    while (   !Archive_eof(&archiveInfo)
           && (failError == ERROR_NONE)
          )
    {
      /* get next archive entry type */
      error = Archive_getNextArchiveEntryType(&archiveInfo,
                                              &archiveFileInfo,
                                              &archiveEntryType
                                             );
      if (error != ERROR_NONE)
      {
        printError("Cannot not read next entry in archive '%s' (error: %s)!\n",
                   String_cString(archiveFileName),
                   Errors_getText(error)
                  );
        if (failError == ERROR_NONE) failError = error;
        break;
      }

      switch (archiveEntryType)
      {
        case ARCHIVE_ENTRY_TYPE_FILE:
          {
            String       fileName;
            FileInfo     fileInfo;
            uint64       fragmentOffset,fragmentSize;
            FragmentNode *fragmentNode;
//            FileInfo   localFileInfo;
            FileHandle   fileHandle;
            bool         equalFlag;
            uint64       length;
            ulong        n;
            ulong        diffIndex;

            /* read file */
            fileName = String_new();
            error = Archive_readFileEntry(&archiveInfo,
                                          &archiveFileInfo,
                                          NULL,
                                          NULL,
                                          NULL,
                                          fileName,
                                          &fileInfo,
                                          &fragmentOffset,
                                          &fragmentSize
                                         );
            if (error != ERROR_NONE)
            {
              printError("Cannot not read 'file' content of archive '%s' (error: %s)!\n",
                         String_cString(archiveFileName),
                         Errors_getText(error)
                        );
              String_delete(fileName);
              if (failError == ERROR_NONE) failError = error;
              break;
            }

            if (   (List_empty(includeEntryList) || EntryList_match(includeEntryList,fileName,PATTERN_MATCH_MODE_EXACT))
                && !PatternList_match(excludePatternList,fileName,PATTERN_MATCH_MODE_EXACT)
               )
            {
              printInfo(2,"  Compare file '%s'...",String_cString(fileName));

              /* check file */
              if (!File_exists(fileName))
              {
                printInfo(2,"FAIL!\n");
                printError("File '%s' not found!\n",String_cString(fileName));
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_FILE_NOT_FOUND;
                }
                break;
              }
              if (File_getType(fileName) != FILE_TYPE_FILE)
              {
                printInfo(2,"FAIL!\n");
                printError("'%s' is not a file!\n",String_cString(fileName));
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_WRONG_FILE_TYPE;
                }
                break;
              }

              /* get file fragment list */
              fragmentNode = FragmentList_find(&fragmentList,fileName);
              if (fragmentNode == NULL)
              {
                fragmentNode = FragmentList_add(&fragmentList,fileName,fileInfo.size);
              }
//FragmentList_print(fragmentNode,String_cString(fileName));

              /* open file */
              error = File_open(&fileHandle,fileName,FILE_OPENMODE_READ);
              if (error != ERROR_NONE)
              {
                printInfo(2,"FAIL!\n");
                printError("Cannot open file '%s' (error: %s)\n",
                           String_cString(fileName),
                           Errors_getText(error)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = error;
                }
                continue;
              }

              /* check file size */
              if (fileInfo.size != File_getSize(&fileHandle))
              {
                printInfo(2,"FAIL!\n");
                printError("'%s' differ in size: expected %lld bytes, found %lld bytes\n",
                           String_cString(fileName),
                           fileInfo.size,
                           File_getSize(&fileHandle)
                          );
                File_close(&fileHandle);
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_FILES_DIFFER;
                }
                continue;
              }

              /* check file content */
              error = File_seek(&fileHandle,fragmentOffset);
              if (error != ERROR_NONE)
              {
                printInfo(2,"FAIL!\n");
                printError("Cannot read file '%s' (error: %s)\n",
                           String_cString(fileName),
                           Errors_getText(error)
                          );
                File_close(&fileHandle);
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = error;
                }
                continue;
              }
              length    = 0;
              equalFlag = TRUE;
              diffIndex = 0;
              while ((length < fragmentSize) && equalFlag)
              {
                n = MIN(fragmentSize-length,BUFFER_SIZE);

                /* read archive, file */
                error = Archive_readData(&archiveFileInfo,archiveBuffer,n);
                if (error != ERROR_NONE)
                {
                  printInfo(2,"FAIL!\n");
                  printError("Cannot not read content of archive '%s' (error: %s)!\n",
                             String_cString(archiveFileName),
                             Errors_getText(error)
                            );
                  if (failError == ERROR_NONE) failError = error;
                  break;
                }
                error = File_read(&fileHandle,buffer,n,NULL);
                if (error != ERROR_NONE)
                {
                  printInfo(2,"FAIL!\n");
                  printError("Cannot read file '%s' (error: %s)\n",
                             String_cString(fileName),
                             Errors_getText(error)
                            );
                  if (jobOptions->stopOnErrorFlag)
                  {
                    failError = error;
                  }
                  break;
                }

                /* compare */
                diffIndex = compare(archiveBuffer,buffer,n);
                equalFlag = (diffIndex >= n);
                if (!equalFlag)
                {
                  printInfo(2,"FAIL!\n");
                  printError("'%s' differ at offset %llu\n",
                             String_cString(fileName),
                             fragmentOffset+length+(uint64)diffIndex
                            );
                  if (jobOptions->stopOnErrorFlag)
                  {
                    failError = ERROR_FILES_DIFFER;
                  }
                  break;
                }

                length += n;
              }
              File_close(&fileHandle);
              if (failError != ERROR_NONE)
              {
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                continue;
              }

#if 0
              /* get local file info */
              /* check file time, permissions, file owner/group */
#endif /* 0 */
              printInfo(2,"ok\n");

              /* add fragment to file fragment list */
              FragmentList_addEntry(fragmentNode,fragmentOffset,fragmentSize);

              /* discard fragment list if file is complete */
              if (FragmentList_checkEntryComplete(fragmentNode))
              {
                FragmentList_remove(&fragmentList,fragmentNode);
              }

              /* free resources */
            }
            else
            {
              /* skip */
              printInfo(3,"  Compare '%s'...skipped\n",String_cString(fileName));
            }

            /* close archive file, free resources */
            Archive_closeEntry(&archiveFileInfo);
            String_delete(fileName);
          }
          break;
        case ARCHIVE_ENTRY_TYPE_IMAGE:
          {
            String       imageName;
            DeviceInfo   deviceInfo;
            uint64       blockOffset,blockCount;
            FragmentNode *fragmentNode;
            DeviceHandle deviceHandle;
            bool         equalFlag;
            uint64       block;
            ulong        bufferBlockCount;
            ulong        diffIndex;

            /* read image */
            imageName = String_new();
            error = Archive_readImageEntry(&archiveInfo,
                                           &archiveFileInfo,
                                           NULL,
                                           NULL,
                                           NULL,
                                           imageName,
                                           &deviceInfo,
                                           &blockOffset,
                                           &blockCount
                                          );
            if (error != ERROR_NONE)
            {
              printError("Cannot not read 'image' content of archive '%s' (error: %s)!\n",
                         String_cString(archiveFileName),
                         Errors_getText(error)
                        );
              String_delete(imageName);
              if (failError == ERROR_NONE) failError = error;
              break;
            }

            if (   (List_empty(includeEntryList) || EntryList_match(includeEntryList,imageName,PATTERN_MATCH_MODE_EXACT))
                && !PatternList_match(excludePatternList,imageName,PATTERN_MATCH_MODE_EXACT)
               )
            {
              printInfo(2,"  Compare image '%s'...",String_cString(imageName));

              /* check if device exists */
              if (!File_exists(imageName))
              {
                printInfo(2,"FAIL!\n");
                printError("Device '%s' not found!\n",String_cString(imageName));
                Archive_closeEntry(&archiveFileInfo);
                String_delete(imageName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_FILE_NOT_FOUND;
                }
                break;
              }

              /* get image fragment list */
              fragmentNode = FragmentList_find(&fragmentList,imageName);
              if (fragmentNode == NULL)
              {
                fragmentNode = FragmentList_add(&fragmentList,imageName,deviceInfo.size);
              }

              /* open device */
              error = Device_open(&deviceHandle,imageName,DEVICE_OPENMODE_READ);
              if (error != ERROR_NONE)
              {
                printInfo(2,"FAIL!\n");
                printError("Cannot open file '%s' (error: %s)\n",
                           String_cString(imageName),
                           Errors_getText(error)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(imageName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = error;
                }
                continue;
              }

              /* check image size */
              if (deviceInfo.size != Device_getSize(&deviceHandle))
              {
                printInfo(2,"FAIL!\n");
                printError("'%s' differ in size: expected %lld bytes, found %lld bytes\n",
                           String_cString(imageName),
                           deviceInfo.size,
                           Device_getSize(&deviceHandle)
                          );
                Device_close(&deviceHandle);
                Archive_closeEntry(&archiveFileInfo);
                String_delete(imageName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_FILES_DIFFER;
                }
                continue;
              }

              /* check image content */
              error = Device_seek(&deviceHandle,blockOffset*(uint64)deviceInfo.blockSize);
              if (error != ERROR_NONE)
              {
                printInfo(2,"FAIL!\n");
                printError("Cannot read file '%s' (error: %s)\n",
                           String_cString(imageName),
                           Errors_getText(error)
                          );
                Device_close(&deviceHandle);
                Archive_closeEntry(&archiveFileInfo);
                String_delete(imageName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = error;
                }
                continue;
              }
              block     = 0LL;
              equalFlag = TRUE;
              diffIndex = 0;
              while ((block < blockCount) && equalFlag)
              {
                assert(deviceInfo.blockSize > 0);
                bufferBlockCount = MIN(blockCount-block,BUFFER_SIZE/deviceInfo.blockSize);

                /* read archive, file */
                error = Archive_readData(&archiveFileInfo,archiveBuffer,bufferBlockCount*deviceInfo.blockSize);
                if (error != ERROR_NONE)
                {
                  printInfo(2,"FAIL!\n");
                  printError("Cannot not read content of archive '%s' (error: %s)!\n",
                             String_cString(archiveFileName),
                             Errors_getText(error)
                            );
                  if (failError == ERROR_NONE) failError = error;
                  break;
                }
                error = Device_read(&deviceHandle,buffer,bufferBlockCount*deviceInfo.blockSize,NULL);
                if (error != ERROR_NONE)
                {
                  printInfo(2,"FAIL!\n");
                  printError("Cannot read file '%s' (error: %s)\n",
                             String_cString(imageName),
                             Errors_getText(error)
                            );
                  if (jobOptions->stopOnErrorFlag)
                  {
                    failError = error;
                  }
                  break;
                }

                /* compare */
                diffIndex = compare(archiveBuffer,buffer,bufferBlockCount*deviceInfo.blockSize);
                equalFlag = (diffIndex >= bufferBlockCount*deviceInfo.blockSize);
                if (!equalFlag)
                {
                  printInfo(2,"FAIL!\n");
                  printError("'%s' differ at offset %llu\n",
                             String_cString(imageName),
                             blockOffset*(uint64)deviceInfo.blockSize+block*(uint64)deviceInfo.blockSize+(uint64)diffIndex
                            );
                  if (jobOptions->stopOnErrorFlag)
                  {
                    failError = ERROR_FILES_DIFFER;
                  }
                  break;
                }

                block += (uint64)bufferBlockCount;
              }
              Device_close(&deviceHandle);
              if (failError != ERROR_NONE)
              {
                Archive_closeEntry(&archiveFileInfo);
                String_delete(imageName);
                continue;
              }

#if 0
              /* get local file info */
              /* check file time, permissions, file owner/group */
#endif /* 0 */
              printInfo(2,"ok\n");

              /* add fragment to file fragment list */
              FragmentList_addEntry(fragmentNode,blockOffset*(uint64)deviceInfo.blockSize,blockCount*(uint64)deviceInfo.blockSize);

              /* discard fragment list if file is complete */
              if (FragmentList_checkEntryComplete(fragmentNode))
              {
                FragmentList_remove(&fragmentList,fragmentNode);
              }

              /* free resources */
            }
            else
            {
              /* skip */
              printInfo(3,"  Compare '%s'...skipped\n",String_cString(imageName));
            }

            /* close archive file, free resources */
            Archive_closeEntry(&archiveFileInfo);
            String_delete(imageName);
          }
          break;
        case ARCHIVE_ENTRY_TYPE_DIRECTORY:
          {
            String   directoryName;
            FileInfo fileInfo;
//            String   localFileName;
//            FileInfo localFileInfo;

            /* read directory */
            directoryName = String_new();
            error = Archive_readDirectoryEntry(&archiveInfo,
                                               &archiveFileInfo,
                                               NULL,
                                               NULL,
                                               directoryName,
                                               &fileInfo
                                              );
            if (error != ERROR_NONE)
            {
              printError("Cannot not read 'directory' content of archive '%s' (error: %s)!\n",
                         String_cString(archiveFileName),
                         Errors_getText(error)
                        );
              String_delete(directoryName);
              if (failError == ERROR_NONE) failError = error;
              break;
            }

            if (   (List_empty(includeEntryList) || EntryList_match(includeEntryList,directoryName,PATTERN_MATCH_MODE_EXACT))
                && !PatternList_match(excludePatternList,directoryName,PATTERN_MATCH_MODE_EXACT)
               )
            {
              printInfo(2,"  Compare directory '%s'...",String_cString(directoryName));

              /* check directory */
              if (!File_exists(directoryName))
              {
                printInfo(2,"FAIL!\n");
                printError("Directory '%s' does not exists!\n",String_cString(directoryName));
                Archive_closeEntry(&archiveFileInfo);
                String_delete(directoryName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_FILE_NOT_FOUND;
                }
                break;
              }
              if (File_getType(directoryName) != FILE_TYPE_DIRECTORY)
              {
                printInfo(2,"FAIL!\n");
                printError("'%s' is not a directory!\n",
                           String_cString(directoryName)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(directoryName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_WRONG_FILE_TYPE;
                }
                break;
              }

#if 0
              /* get local file info */
              error = File_getFileInfo(directoryName,&localFileInfo);
              if (error != ERROR_NONE)
              {
                printError("Cannot not read local directory '%s' (error: %s)!\n",
                           String_cString(directoryName),
                           Errors_getText(error)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(directoryName);
                if (failError == ERROR_NONE) failError = error;
                break;
              }

              /* check file time, permissions, file owner/group */
#endif /* 0 */
              printInfo(2,"ok\n");

              /* free resources */
            }
            else
            {
              /* skip */
              printInfo(3,"  Compare '%s'...skipped\n",String_cString(directoryName));
            }

            /* close archive file */
            Archive_closeEntry(&archiveFileInfo);
            String_delete(directoryName);
          }
          break;
        case ARCHIVE_ENTRY_TYPE_LINK:
          {
            String   linkName;
            String   fileName;
            FileInfo fileInfo;
            String   localFileName;
//            FileInfo localFileInfo;

            /* read link */
            linkName = String_new();
            fileName = String_new();
            error = Archive_readLinkEntry(&archiveInfo,
                                          &archiveFileInfo,
                                          NULL,
                                          NULL,
                                          linkName,
                                          fileName,
                                          &fileInfo
                                         );
            if (error != ERROR_NONE)
            {
              printError("Cannot not read 'link' content of archive '%s' (error: %s)!\n",
                         String_cString(archiveFileName),
                         Errors_getText(error)
                        );
              String_delete(fileName);
              String_delete(linkName);
              if (failError == ERROR_NONE) failError = error;
              break;
            }

            if (   (List_empty(includeEntryList) || EntryList_match(includeEntryList,linkName,PATTERN_MATCH_MODE_EXACT))
                && !PatternList_match(excludePatternList,linkName,PATTERN_MATCH_MODE_EXACT)
               )
            {
              printInfo(2,"  Compare link '%s'...",String_cString(linkName));

              /* check link */
              if (!File_exists(linkName))
              {
                printInfo(2,"FAIL!\n");
                printError("Link '%s' -> '%s' does not exists!\n",
                           String_cString(linkName),
                           String_cString(fileName)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                String_delete(linkName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_FILE_NOT_FOUND;
                }
                break;
              }
              if (File_getType(linkName) != FILE_TYPE_LINK)
              {
                printInfo(2,"FAIL!\n");
                printError("'%s' is not a link!\n",
                           String_cString(linkName)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                String_delete(linkName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_WRONG_FILE_TYPE;
                }
                break;
              }

              /* check link content */
              localFileName = String_new();
              error = File_readLink(linkName,localFileName);
              if (error != ERROR_NONE)
              {
                printError("Cannot not read local file '%s' (error: %s)!\n",
                           String_cString(linkName),
                           Errors_getText(error)
                          );
                String_delete(localFileName);
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                String_delete(linkName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = error;
                }
                break;
              }
              if (!String_equals(fileName,localFileName))
              {
                printInfo(2,"FAIL!\n");
                printError("Link '%s' does not contain file '%s'!\n",
                           String_cString(linkName),
                           String_cString(fileName)
                          );
                String_delete(localFileName);
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                String_delete(linkName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_FILES_DIFFER;
                }
                break;
              }
              String_delete(localFileName);

#if 0
              /* get local file info */
              error = File_getFileInfo(linkName,&localFileInfo);
              if (error != ERROR_NONE)
              {
                printError("Cannot not read local file '%s' (error: %s)!\n",
                           String_cString(linkName),
                           Errors_getText(error)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                String_delete(linkName);
                if (failError == ERROR_NONE) failError = error;
                break;
              }

              /* check file time, permissions, file owner/group */
#endif /* 0 */
              printInfo(2,"ok\n");

              /* free resources */
            }
            else
            {
              /* skip */
              printInfo(3,"  Compare '%s'...skipped\n",String_cString(linkName));
            }

            /* close archive file */
            Archive_closeEntry(&archiveFileInfo);
            String_delete(fileName);
            String_delete(linkName);
          }
          break;
        case ARCHIVE_ENTRY_TYPE_SPECIAL:
          {
            String   fileName;
            FileInfo fileInfo;
            FileInfo localFileInfo;

            /* read special */
            fileName = String_new();
            error = Archive_readSpecialEntry(&archiveInfo,
                                             &archiveFileInfo,
                                             NULL,
                                             NULL,
                                             fileName,
                                             &fileInfo
                                            );
            if (error != ERROR_NONE)
            {
              printError("Cannot not read 'special' content of archive '%s' (error: %s)!\n",
                         String_cString(archiveFileName),
                         Errors_getText(error)
                        );
              String_delete(fileName);
              if (failError == ERROR_NONE) failError = error;
              break;
            }

            if (   (List_empty(includeEntryList) || EntryList_match(includeEntryList,fileName,PATTERN_MATCH_MODE_EXACT))
                && !PatternList_match(excludePatternList,fileName,PATTERN_MATCH_MODE_EXACT)
               )
            {
              printInfo(2,"  Compare special device '%s'...",String_cString(fileName));

              /* check special device */
              if (!File_exists(fileName))
              {
                printInfo(2,"FAIL!\n");
                printError("Special device '%s' does not exists!\n",
                           String_cString(fileName)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_FILE_NOT_FOUND;
                }
                break;
              }
              if (File_getType(fileName) != FILE_TYPE_SPECIAL)
              {
                printInfo(2,"FAIL!\n");
                printError("'%s' is not a special device!\n",
                           String_cString(fileName)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = ERROR_WRONG_FILE_TYPE;
                }
                break;
              }

              /* check special settings */
              error = File_getFileInfo(fileName,&localFileInfo);
              if (error != ERROR_NONE)
              {
                printError("Cannot not read local file '%s' (error: %s)!\n",
                           String_cString(fileName),
                           Errors_getText(error)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = error;
                }
                break;
              }
              if (fileInfo.specialType != localFileInfo.specialType)
              {
                printError("Different types of special device '%s'!\n",
                           String_cString(fileName)
                          );
                Archive_closeEntry(&archiveFileInfo);
                String_delete(fileName);
                if (jobOptions->stopOnErrorFlag)
                {
                  failError = error;
                }
                break;
              }
              if (   (fileInfo.specialType == FILE_SPECIAL_TYPE_CHARACTER_DEVICE)
                  || (fileInfo.specialType == FILE_SPECIAL_TYPE_BLOCK_DEVICE)
                 )
              {
                if (fileInfo.major != localFileInfo.major)
                {
                  printError("Different major numbers of special device '%s'!\n",
                             String_cString(fileName)
                            );
                  Archive_closeEntry(&archiveFileInfo);
                  String_delete(fileName);
                  if (jobOptions->stopOnErrorFlag)
                  {
                    failError = error;
                  }
                  break;
                }
                if (fileInfo.minor != localFileInfo.minor)
                {
                  printError("Different minor numbers of special device '%s'!\n",
                             String_cString(fileName)
                            );
                  Archive_closeEntry(&archiveFileInfo);
                  String_delete(fileName);
                  if (jobOptions->stopOnErrorFlag)
                  {
                    failError = error;
                  }
                  break;
                }
              }

#if 0

              /* check file time, permissions, file owner/group */
#endif /* 0 */

              printInfo(2,"ok\n");

              /* free resources */
            }
            else
            {
              /* skip */
              printInfo(3,"  Compare '%s'...skipped\n",String_cString(fileName));
            }

            /* close archive file */
            Archive_closeEntry(&archiveFileInfo);
            String_delete(fileName);
          }
          break;
        default:
          #ifndef NDEBUG
            HALT_INTERNAL_ERROR_UNHANDLED_SWITCH_CASE();
          #endif /* NDEBUG */
          break; /* not reached */
      }
    }

    /* close archive */
    Archive_close(&archiveInfo);
  }

  /* check fragment lists */
  for (fragmentNode = fragmentList.head; fragmentNode != NULL; fragmentNode = fragmentNode->next)
  {
    if (!FragmentList_checkEntryComplete(fragmentNode))
    {
      printInfo(0,"Warning: incomplete entry '%s'\n",String_cString(fragmentNode->name));
      if (failError == ERROR_NONE) failError = ERROR_FILE_INCOMPLETE;
    }
  }

  /* free resources */
  String_delete(archiveFileName);
  FragmentList_done(&fragmentList);
  free(buffer);
  free(archiveBuffer);

  return failError;
}
示例#30
0
static void ethInterface(Dict* config, struct Context* ctx)
{
    List* ifaces = Dict_getList(config, String_CONST("ETHInterface"));
    if (!ifaces) {
        ifaces = List_new(ctx->alloc);
        List_addDict(ifaces, Dict_getDict(config, String_CONST("ETHInterface")), ctx->alloc);
    }

    uint32_t count = List_size(ifaces);

    for (uint32_t i = 0; i < count; i++) {
        Dict *eth = List_getDict(ifaces, i);
        if (!eth) { continue; }
        String* deviceStr = Dict_getString(eth, String_CONST("bind"));
        if (!deviceStr || !String_equals(String_CONST("all"), deviceStr)) { continue; }
        Log_info(ctx->logger, "Setting up all ETHInterfaces...");
        Dict* res = NULL;
        Dict* d = Dict_new(ctx->alloc);
        if (rpcCall0(String_CONST("ETHInterface_listDevices"), d, ctx, ctx->alloc, &res, false)) {
            Log_info(ctx->logger, "Getting device list failed");
            break;
        }
        List* devs = Dict_getList(res, String_CONST("devices"));
        uint32_t devCount = List_size(devs);
        for (uint32_t j = 0; j < devCount; j++) {
            Dict* d = Dict_new(ctx->alloc);
            String* deviceName = List_getString(devs, j);
            // skip loopback...
            if (String_equals(String_CONST("lo"), deviceName)) { continue; }
            Dict_putString(d, String_CONST("bindDevice"), deviceName, ctx->alloc);
            Dict* resp;
            Log_info(ctx->logger, "Creating new ETHInterface [%s]", deviceName->bytes);
            if (rpcCall0(String_CONST("ETHInterface_new"), d, ctx, ctx->alloc, &resp, false)) {
                Log_warn(ctx->logger, "Failed to create ETHInterface.");
                continue;
            }
            int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber")));
            ethInterfaceSetBeacon(ifNum, eth, ctx);
        }
        return;
    }

    for (uint32_t i = 0; i < count; i++) {
        Dict *eth = List_getDict(ifaces, i);
        if (!eth) { continue; }
        // Setup the interface.
        String* deviceStr = Dict_getString(eth, String_CONST("bind"));
        Log_info(ctx->logger, "Setting up ETHInterface [%d].", i);
        Dict* d = Dict_new(ctx->alloc);
        if (deviceStr) {
            Log_info(ctx->logger, "Binding to device [%s].", deviceStr->bytes);
            Dict_putString(d, String_CONST("bindDevice"), deviceStr, ctx->alloc);
        }
        Dict* resp = NULL;
        if (rpcCall0(String_CONST("ETHInterface_new"), d, ctx, ctx->alloc, &resp, false)) {
            Log_warn(ctx->logger, "Failed to create ETHInterface.");
            continue;
        }
        int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber")));
        ethInterfaceSetBeacon(ifNum, eth, ctx);

        // Make the connections.
        Dict* connectTo = Dict_getDict(eth, String_CONST("connectTo"));
        if (connectTo) {
            Log_info(ctx->logger, "ETHInterface should connect to a specific node.");
            struct Dict_Entry* entry = *connectTo;
            while (entry != NULL) {
                String* key = (String*) entry->key;
                if (entry->val->type != Object_DICT) {
                    Log_critical(ctx->logger, "interfaces.ETHInterface.connectTo: entry [%s] "
                                               "is not a dictionary type.", key->bytes);
                    exit(-1);
                }
                Dict* value = entry->val->as.dictionary;

                Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);

                struct Allocator* perCallAlloc = Allocator_child(ctx->alloc);
                // Turn the dict from the config into our RPC args dict by filling in all
                // the arguments,
                Dict_putString(value, String_CONST("macAddress"), key, perCallAlloc);
                Dict_putInt(value, String_CONST("interfaceNumber"), ifNum, perCallAlloc);
                rpcCall(String_CONST("ETHInterface_beginConnection"), value, ctx, perCallAlloc);
                Allocator_free(perCallAlloc);

                entry = entry->next;
            }
        }
    }
}