Beispiel #1
0
static int handle_status(void *object, int number, uint8_t status, void *userdata)
{
    Friend_Connections *const fr_c = (Friend_Connections *)object;
    Friend_Conn *const friend_con = get_conn(fr_c, number);

    if (!friend_con) {
        return -1;
    }

    bool call_cb = 0;

    if (status) {  /* Went online. */
        call_cb = 1;
        friend_con->status = FRIENDCONN_STATUS_CONNECTED;
        friend_con->ping_lastrecv = unix_time();
        friend_con->share_relays_lastsent = 0;
        onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
    } else {  /* Went offline. */
        if (friend_con->status != FRIENDCONN_STATUS_CONNECTING) {
            call_cb = 1;
            friend_con->dht_pk_lastrecv = unix_time();
            onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
        }

        friend_con->status = FRIENDCONN_STATUS_CONNECTING;
        friend_con->crypt_connection_id = -1;
        friend_con->hosting_tcp_relay = 0;
    }

    if (call_cb) {
        unsigned int i;

        for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
            if (friend_con->callbacks[i].status_callback) {
                friend_con->callbacks[i].status_callback(
                    friend_con->callbacks[i].callback_object,
                    friend_con->callbacks[i].callback_id, status, userdata);
            }
        }
    }

    return 0;
}
Beispiel #2
0
boxfile * obj_to_file(jobj * obj)
{
	list_iter it;
	jobj * item;
	boxfile * f = (boxfile*) malloc(sizeof(boxfile));
	
	memset(f, 0, sizeof(boxfile));
	it = list_get_iter(obj->children);
	for(; it; it = list_iter_next(it)) {
		item = list_iter_getval(it);
		if(!strcmp(item->key,"id")) f->id = strdup(item->value);
		else if(!strcmp(item->key, "size")) f->size = atoll(item->value);
		else if(!strcmp(item->key, "name")) f->name = strdup(item->value);
		else if(!strcmp(item->key, "created_at")) f->ctime = unix_time(item->value);
		else if(!strcmp(item->key, "modified_at")) f->mtime = unix_time(item->value);
	}

	return f;
}
Beispiel #3
0
static int handle_announce_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length)
{
    Onion_Client *onion_c = object;

    if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE)
        return 1;

    uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;

    uint8_t public_key[crypto_box_PUBLICKEYBYTES];
    IP_Port ip_port;
    uint32_t path_num;
    uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port, &path_num);

    if (num > onion_c->num_friends)
        return 1;

    uint8_t plain[1 + ONION_PING_ID_SIZE + len_nodes];
    int len = -1;

    if (num == 0) {
        len = decrypt_data(public_key, onion_c->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
                           packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES,
                           length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain);
    } else {
        if (onion_c->friends_list[num - 1].status == 0)
            return 1;

        len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key,
                           packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
                           packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES,
                           length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain);
    }

    if ((uint32_t)len != sizeof(plain))
        return 1;

    if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, path_num) == -1)
        return 1;

    if (len_nodes != 0) {
        Node_format nodes[MAX_SENT_NODES];
        int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes, 0);

        if (num_nodes <= 0)
            return 1;

        if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1)
            return 1;
    }

    //TODO: LAN vs non LAN ips?, if we are connected only to LAN, are we offline?
    onion_c->last_packet_recv = unix_time();
    return 0;
}
Beispiel #4
0
static int handle_fakeid_announce(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint32_t length)
{
    Onion_Client *onion_c = object;

    if (length < FAKEID_DATA_MIN_LENGTH)
        return 1;

    if (length > FAKEID_DATA_MAX_LENGTH)
        return 1;

    int friend_num = onion_friend_num(onion_c, source_pubkey);

    if (friend_num == -1)
        return 1;

    uint64_t no_replay;
    memcpy(&no_replay, data + 1, sizeof(uint64_t));
    net_to_host((uint8_t *) &no_replay, sizeof(no_replay));

    if (no_replay <= onion_c->friends_list[friend_num].last_noreplay)
        return 1;

    onion_c->friends_list[friend_num].last_noreplay = no_replay;
    onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t), current_time_monotonic());
    onion_c->friends_list[friend_num].last_seen = unix_time();

    uint16_t len_nodes = length - FAKEID_DATA_MIN_LENGTH;

    if (len_nodes != 0) {
        Node_format nodes[MAX_SENT_NODES];
        int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES,
                                     len_nodes, 1);

        if (num_nodes <= 0)
            return 1;

        int i;

        for (i = 0; i < num_nodes; ++i) {
            uint8_t family = nodes[i].ip_port.ip.family;

            if (family == AF_INET || family == AF_INET6) {
                DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id);
            } else if (family == TCP_INET || family == TCP_INET6) {
                if (onion_c->friends_list[friend_num].tcp_relay_node_callback) {
                    void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object;
                    uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number;
                    onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, nodes[i].ip_port, nodes[i].client_id);
                }
            }
        }
    }

    return 0;
}
Beispiel #5
0
void do_onion_client(Onion_Client *onion_c)
{
    unsigned int i;

    if (onion_c->last_run == unix_time())
        return;

    for (i = 0; i < NODE_POPULATE_TIMES; ++i)
        populate_path_nodes(onion_c);

    do_announce(onion_c);

    if (onion_isconnected(onion_c)) {
        for (i = 0; i < onion_c->num_friends; ++i) {
            do_friend(onion_c, i);
        }
    }

    onion_c->last_run = unix_time();
}
Beispiel #6
0
/** Truncate an Ext2 inode.
 * @todo		Triple indirect blocks.
 * @param inode		Inode to truncate. Should be locked.
 * @param size		New size of node.
 * @return		Status code describing result of the operation. */
static status_t ext2_inode_truncate(ext2_inode_t *inode, offset_t size) {
	status_t ret;
	size_t count;
	int i;

	assert(!(inode->mount->parent->flags & FS_MOUNT_RDONLY));

	if(inode->size <= size) {
		return STATUS_SUCCESS;
	}

	/* TODO. I'm lazy. */
	if(size > 0) {
		kprintf(LOG_WARN, "ext2: truncate not yet support for size > 0\n");
		return STATUS_NOT_IMPLEMENTED;
	}

	/* Don't support tri-indirect yet, check now so we don't discover
	 * one when we've already freed part of the file. */
	if(le32_to_cpu(inode->disk.i_block[EXT2_TIND_BLOCK]) != 0) {
		kprintf(LOG_WARN, "ext2: tri-indirect blocks not yet supported!\n");
		return STATUS_NOT_IMPLEMENTED;
	}

	count = ROUND_UP(inode->size, inode->mount->block_size) / inode->mount->block_size;
	file_map_invalidate(inode->map, 0, count);
	vm_cache_resize(inode->cache, size);
	inode->size = size;
	inode->disk.i_mtime = cpu_to_le32(USECS2SECS(unix_time()));
	ext2_inode_flush(inode);

	for(i = 0; i < EXT2_N_BLOCKS; i++) {
		if(le32_to_cpu(inode->disk.i_block[i]) == 0) {
			continue;
		} else if(i < EXT2_NDIR_BLOCKS) {
			ret = ext2_inode_block_free(inode, &inode->disk.i_block[i]);
			if(ret != STATUS_SUCCESS) {
				return ret;
			}
		} else if(i == EXT2_IND_BLOCK) {
			ret = ext2_inode_iblock_free(inode, &inode->disk.i_block[i]);
			if(ret != STATUS_SUCCESS) {
				return ret;
			}
		} else if(i == EXT2_DIND_BLOCK) {
			ret = ext2_inode_biblock_free(inode, &inode->disk.i_block[i]);
			if(ret != STATUS_SUCCESS) {
				return ret;
			}
		}
	}

	return STATUS_SUCCESS;
}
Beispiel #7
0
/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
static void LANdiscovery(Friend_Connections *fr_c)
{
    if (fr_c->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) {
        const uint16_t first = fr_c->next_LANport;
        uint16_t last = first + PORTS_PER_DISCOVERY;
        last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last;

        // Always send to default port
        lan_discovery_send(net_htons(TOX_PORT_DEFAULT), fr_c->dht);

        // And check some extra ports
        for (uint16_t port = first; port < last; port++) {
            lan_discovery_send(net_htons(port), fr_c->dht);
        }

        // Don't include default port in port range
        fr_c->next_LANport = last != TOX_PORTRANGE_TO ? last : TOX_PORTRANGE_FROM + 1;
        fr_c->last_LANdiscovery = unix_time();
    }
}
Beispiel #8
0
/******************************************************************************
   Description:
      Conversion between the UNIX time and the (year, month,
      day, hour, minute, second) representation. If "time" is
      non-zero, this function returns the year, month,
      day, hour, minute and second as converted from "time".

   Inputs:
      time - the UNIX time;

   Outputs:
      year - year (e.g. 1995; >= 1970)
      month - month number (1 through 12)
      day - day number (1, 2, 3, ...)
      hour - hour (0 through 23)
      minute - minute (0 through 59)
      second - second (0 through 59)

   Returns:
      The function returns 0 on success or -1 on failure (an
      argument is out of range).

   Notes:
      See misc_unix_time.c in cpc100/lib004.

******************************************************************************/
int RPGCS_unix_time_to_ymdhms( time_t time, int *year, int *month, int *day,
                               int *hour, int *minute, int *second ) {

    /* Insure the time value is not zero. */
    if( time == 0 )
        return(-1);

    return( unix_time( &time, year, month, day, hour, minute, second ) );

    /* End of RPGCS_unix_time_to_ymdhms() */
}
Beispiel #9
0
/******************************************************************************
   Description:
      Conversion between the UNIX time and the (year, month, day, hour,
      minute, second) representation. "year", "month", "day", "hour",
      "minute" and "second" are converted to UNIX time and the result is
      stored in "time".

   Inputs:
      year - year (e.g. 1995; >= 1970)
      month - month number (1 through 12)
      day - day number (1, 2, 3, ...)
      hour - hour (0 through 23)
      minute - minute (0 through 59)
      second - second (0 through 59)

   Outputs:
      time - the UNIX time;

   Returns:
      The function returns 0 on success or -1 on failure (an
      argument is out of range).

   Notes:
      See misc_unix_time.c in cpc100/lib004.

******************************************************************************/
int RPGCS_ymdhms_to_unix_time( time_t *time, int year, int month, int day,
                               int hour, int minute, int second ) {

    /* Ensure that the time value is zero. */
    if( *time != 0 )
        *time = 0;

    return( unix_time( time, &year, &month, &day, &hour, &minute, &second ) );

    /* End of RPGCS_ymdhms_to_unix_time() */
}
Beispiel #10
0
/** Get information about a memory file.
 * @param handle	File handle structure.
 * @param info		Information structure to fill in. */
static void memory_file_info(file_handle_t *handle, file_info_t *info) {
	memory_file_t *file = (memory_file_t *)handle->file;

	info->id = 0;
	info->mount = 0;
	info->type = file->file.type;
	info->block_size = 1;
	info->size = file->size;
	info->links = 1;
	info->created = info->accessed = info->modified = unix_time();
}
static void do_TCP_confirmed(TCP_Server *TCP_server)
{
    uint32_t i;

    for (i = 0; i < TCP_server->size_accepted_connections; ++i) {
        TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[i];

        if (conn->status != TCP_STATUS_CONFIRMED)
            continue;

        if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) {
            uint8_t ping[1 + sizeof(uint64_t)];
            ping[0] = TCP_PACKET_PING;
            uint64_t ping_id = random_64b();

            if (!ping_id)
                ++ping_id;

            memcpy(ping + 1, &ping_id, sizeof(uint64_t));
            int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping));

            if (ret == 1) {
                conn->last_pinged = unix_time();
                conn->ping_id = ping_id;
            }
        }

        if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) {
            kill_TCP_connection(conn);
            del_accepted(TCP_server, i);
            continue;
        }

        send_pending_data(conn);
        uint8_t packet[MAX_PACKET_SIZE];
        int len;

        while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key,
                      conn->recv_nonce, packet, sizeof(packet)))) {
            if (len == -1) {
                kill_TCP_connection(conn);
                del_accepted(TCP_server, i);
                break;
            }

            if (handle_TCP_packet(TCP_server, i, packet, len) == -1) {
                kill_TCP_connection(conn);
                del_accepted(TCP_server, i);
                break;
            }
        }
    }
}
static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t length)
{
    Onion_Client *onion_c = object;

    if (length < FAKEID_DATA_MIN_LENGTH)
        return 1;

    if (length > FAKEID_DATA_MAX_LENGTH)
        return 1;

    if ((length - FAKEID_DATA_MIN_LENGTH) % sizeof(Node_format) != 0)
        return 1;

    int friend_num = onion_friend_num(onion_c, source_pubkey);

    if (friend_num == -1)
        return 1;

    uint64_t no_replay;
    net_to_host(data + 1, sizeof(no_replay));
    memcpy(&no_replay, data + 1, sizeof(uint64_t));

    if (no_replay <= onion_c->friends_list[friend_num].last_noreplay)
        return 1;

    onion_c->friends_list[friend_num].last_noreplay = no_replay;

    if (memcmp(data + 1 + sizeof(uint64_t), onion_c->friends_list[friend_num].fake_client_id,
               crypto_box_PUBLICKEYBYTES) != 0) {
        DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);

        onion_c->friends_list[friend_num].last_seen = unix_time();

        if (DHT_addfriend(onion_c->dht, data + 1 + sizeof(uint64_t)) == 1) {
            return 1;
        }

        onion_c->friends_list[friend_num].is_fake_clientid = 1;
        memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES);
    }

    uint16_t num_nodes = (length - FAKEID_DATA_MIN_LENGTH) / sizeof(Node_format);
    Node_format nodes[num_nodes];
    memcpy(nodes, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(nodes));
    uint32_t i;

    for (i = 0; i < num_nodes; ++i) {
        to_host_family(&nodes[i].ip_port.ip);
        DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id);
    }

    return 0;
}
/* Create a new path or use an old suitable one (if pathnum is valid)
 * or a rondom one from onion_paths.
 *
 * return -1 on failure
 * return 0 on success
 *
 * TODO: Make this function better, it currently probably is vulnerable to some attacks that
 * could de anonimize us.
 */
static int random_path(DHT *dht, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path)
{
    if (pathnum >= NUMBER_ONION_PATHS)
        pathnum = rand() % NUMBER_ONION_PATHS;

    if (is_timeout(onion_paths->last_path_success[pathnum], ONION_PATH_TIMEOUT)
            || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)) {
        Node_format nodes[3];

        if (random_nodes_path(dht, nodes, 3) != 3)
            return -1;

        if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1)
            return -1;

        onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT;
        onion_paths->path_creation_time[pathnum] = unix_time();
    }

    memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path));
    return 0;
}
Beispiel #14
0
static int handle_packet(void *object, int number, uint8_t *data, uint16_t length, void *userdata)
{
    if (length == 0)
        return -1;

    Friend_Connections *fr_c = object;
    Friend_Conn *friend_con = get_conn(fr_c, number);

    if (!friend_con)
        return -1;

    if (data[0] == PACKET_ID_FRIEND_REQUESTS) {
        if (fr_c->fr_request_callback)
            fr_c->fr_request_callback(fr_c->fr_request_object, friend_con->real_public_key, data, length);

        return 0;
    } else if (data[0] == PACKET_ID_ALIVE) {
        friend_con->ping_lastrecv = unix_time();
        return 0;
    } else if (data[0] == PACKET_ID_SHARE_RELAYS) {
        Node_format nodes[MAX_SHARED_RELAYS];
        int n;

        if ((n = unpack_nodes(nodes, MAX_SHARED_RELAYS, NULL, data + 1, length - 1, 1)) == -1)
            return -1;

        int j;

        for (j = 0; j < n; j++) {
            friend_add_tcp_relay(fr_c, number, nodes[j].ip_port, nodes[j].public_key);
        }

        return 0;
    }

    unsigned int i;

    for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
        if (friend_con->callbacks[i].data_callback)
            friend_con->callbacks[i].data_callback(
                friend_con->callbacks[i].data_callback_object,
                friend_con->callbacks[i].data_callback_id, data, length, userdata);

        friend_con = get_conn(fr_c, number);

        if (!friend_con)
            return -1;
    }

    return 0;
}
Beispiel #15
0
static int handle_sendnodes(Group_Chat *chat, IP_Port source, int peernum, const uint8_t *data, uint32_t len)
{
    if ((uint32_t)peernum >= chat->numpeers)
        return 1;

    if (len > sizeof(sendnodes_data) || len < sizeof(uint64_t))
        return 1;

    if ((len - sizeof(uint64_t)) % sizeof(groupchat_nodes) != 0)
        return 1;

    if (is_timeout(chat->group[peernum].last_pinged, GROUP_PING_TIMEOUT))
        return 1;

    sendnodes_data contents;
    memcpy(&contents, data, len);

    if (contents.pingid != chat->group[peernum].pingid)
        return 1;

    uint16_t numnodes = (len - sizeof(contents.pingid)) / sizeof(groupchat_nodes);
    uint32_t i;

    IPPTs ippts_send;
    ippts_send.timestamp = unix_time();

    for (i = 0; i < numnodes; ++i) {
        if (peer_okping(chat, contents.nodes[i].client_id) > 0) {
            int peern = peer_in_chat(chat, contents.nodes[i].client_id);

            if (peern == -1) { /*NOTE: This is just for testing and will be removed later.*/
                peern = addpeer(chat, contents.nodes[i].client_id);
            }

            if (peern == -1)
                continue;

            to_host_family(&contents.nodes[i].ip_port.ip);
            send_getnodes(chat, contents.nodes[i].ip_port, peern);

            if (chat->assoc) {
                ippts_send.ip_port = contents.nodes[i].ip_port;
                Assoc_add_entry(chat->assoc, contents.nodes[i].client_id, &ippts_send, NULL, 0);
            }
        }
    }

    int ok = add_closepeer(chat, chat->group[peernum].client_id, source);

    return 0;
}
Beispiel #16
0
static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
{
    if (friendnum >= onion_c->num_friends)
        return;

    if (onion_c->friends_list[friendnum].status == 0)
        return;

    uint32_t i, count = 0;
    Onion_Node *list_nodes = onion_c->friends_list[friendnum].clients_list;

    for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
        if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
            continue;

        ++count;

        if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) {
            if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0) == 0) {
                list_nodes[i].last_pinged = unix_time();
            }
        }
    }

    if (count < MAX_ONION_CLIENTS / 2) {
        Node_format nodes_list[MAX_SENT_NODES];
        uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->friends_list[i].real_client_id, nodes_list,
                                             rand() % 2 ? AF_INET : AF_INET6, rand() % 2, 1);

        for (i = 0; i < num_nodes; ++i)
            client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0);
    }

    /* send packets to friend telling them our fake DHT id. */
    if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_sent, ONION_FAKEID_INTERVAL))
        if (send_fakeid_announce(onion_c, friendnum) > 3)
            onion_c->friends_list[friendnum].last_fakeid_sent = unix_time();
}
Beispiel #17
0
/* main friend_connections loop. */
void do_friend_connections(Friend_Connections *fr_c, void *userdata)
{
    const uint64_t temp_time = unix_time();

    for (uint32_t i = 0; i < fr_c->num_cons; ++i) {
        Friend_Conn *const friend_con = get_conn(fr_c, i);

        if (friend_con) {
            if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) {
                if (friend_con->dht_pk_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    if (friend_con->dht_lock) {
                        DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
                        friend_con->dht_lock = 0;
                        memset(friend_con->dht_temp_pk, 0, CRYPTO_PUBLIC_KEY_SIZE);
                    }
                }

                if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    friend_con->dht_ip_port.ip.family = 0;
                }

                if (friend_con->dht_lock) {
                    if (friend_new_connection(fr_c, i) == 0) {
                        set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
                        connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */
                    }
                }
            } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
                if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
                    send_ping(fr_c, i);
                }

                if (friend_con->share_relays_lastsent + SHARE_RELAYS_INTERVAL < temp_time) {
                    send_relays(fr_c, i);
                }

                if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
                    /* If we stopped receiving ping packets, kill it. */
                    crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
                    friend_con->crypt_connection_id = -1;
                    handle_status(fr_c, i, 0, userdata); /* Going offline. */
                }
            }
        }
    }

    if (fr_c->local_discovery_enabled) {
        LANdiscovery(fr_c);
    }
}
/*
 * Add a peer to the group chat.
 *
 * return peernum if success or peer already in chat.
 * return -1 if error.
 */
static int addpeer(Group_Chat *chat, uint8_t *client_id)
{
    int peernum = peer_in_chat(chat, client_id);

    if (peernum != -1)
        return peernum;

    Group_Peer *temp;
    temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1));

    if (temp == NULL)
        return -1;

    memset(&(temp[chat->numpeers]), 0, sizeof(Group_Peer));
    chat->group = temp;

    id_copy(chat->group[chat->numpeers].client_id, client_id);
    chat->group[chat->numpeers].last_recv = unix_time();
    chat->group[chat->numpeers].last_recv_msgping = unix_time();
    ++chat->numpeers;

    return (chat->numpeers - 1);
}
Beispiel #19
0
static int ping_groupchat(Group_Chats *g_c, int groupnumber)
{
    Group_c *g = get_group_c(g_c, groupnumber);

    if (!g)
        return -1;

    if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) {
        if (group_ping_send(g_c, groupnumber) != -1) /* Ping */
            g->last_sent_ping = unix_time();
    }

    return 0;
}
Beispiel #20
0
/*
 * Add a peer to the group chat.
 *
 * return peer_index if success or peer already in chat.
 * return -1 if error.
 */
static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk,
                   uint16_t peer_number)
{
    Group_c *g = get_group_c(g_c, groupnumber);

    if (!g)
        return -1;

    //TODO
    int peer_index = peer_in_chat(g, real_pk);

    if (peer_index != -1) {
        id_copy(g->group[peer_index].temp_pk, temp_pk);

        if (g->group[peer_index].peer_number != peer_number)
            return -1;

        return peer_index;
    }

    peer_index = get_peer_index(g, peer_number);

    if (peer_index != -1)
        return -1;

    Group_Peer *temp;
    temp = realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));

    if (temp == NULL)
        return -1;

    memset(&(temp[g->numpeers]), 0, sizeof(Group_Peer));
    g->group = temp;

    id_copy(g->group[g->numpeers].real_pk, real_pk);
    id_copy(g->group[g->numpeers].temp_pk, temp_pk);
    g->group[g->numpeers].peer_number = peer_number;

    g->group[g->numpeers].last_recv = unix_time();
    ++g->numpeers;

    add_to_closest(g_c, groupnumber, real_pk, temp_pk);

    if (g_c->peer_namelistchange)
        g_c->peer_namelistchange(g_c->m, groupnumber, g->numpeers - 1, CHAT_CHANGE_PEER_ADD,
                                 g_c->group_namelistchange_userdata);

    return (g->numpeers - 1);
}
Beispiel #21
0
static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, const uint8_t *client_id)
{
    uint32_t i;

    for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) {
        if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME))
            if (memcmp(last_pinged[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0)
                return 0;
    }

    memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].client_id, client_id, crypto_box_PUBLICKEYBYTES);
    last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time();
    ++*last_pinged_index;
    return 1;
}
Beispiel #22
0
/** Read to an Ext2 inode.
 * @param inode		Inode to write to.
 * @param buf		Buffer containing data to write.
 * @param count		Number of bytes to write.
 * @param offset	Offset into inode to write to.
 * @param nonblock	Whether the operation is required to not block.
 * @return		Status code describing result of the operation. */
status_t ext2_inode_write(ext2_inode_t *inode, const void *buf, size_t count, offset_t offset,
                          bool nonblock, size_t *bytesp) {
	uint32_t start, blocks, i;
	uint64_t raw;
	status_t ret;

	mutex_lock(&inode->lock);

	/* Attempt to resize the node if necessary. */
	if((offset + count) > inode->size) {    
		inode->size = offset + count;
		vm_cache_resize(inode->cache, inode->size);
		ext2_inode_flush(inode);
	}

	/* Now we need to reserve blocks on the filesystem. */
	start = offset / inode->mount->block_size;
	blocks = (ROUND_UP(offset + count, inode->mount->block_size) / inode->mount->block_size) - start;
	for(i = 0; i < blocks; i++) {
		ret = file_map_lookup(inode->map, start + i, &raw);
		if(ret != STATUS_SUCCESS) {
			dprintf("ext2: failed to lookup raw block for inode %p(%" PRIu32 ") (%d)\n",
			        inode, inode->num, ret);
			return ret;
		}

		/* If the block number is 0, then allocate a new block. The
		 * call to ext2_inode_block_alloc() invalidates the file map
		 * entries. */
		if(raw == 0) {
			ret = ext2_inode_block_alloc(inode, start + i, nonblock);
			if(ret != STATUS_SUCCESS) {
				dprintf("ext2: failed to allocate raw block for inode %p(%" PRIu32 ") (%d)\n",
				        inode, inode->num, ret);
				return ret;
			}
		}
	}

	mutex_unlock(&inode->lock);

	ret = vm_cache_write(inode->cache, buf, count, offset, nonblock, bytesp);
	if(*bytesp) {
		inode->disk.i_mtime = cpu_to_le32(USECS2SECS(unix_time()));
	}

	return ret;
}
Beispiel #23
0
/* Start a secure connection with other peer who has public_key and ip_port.
 *
 *  return -1 if failure.
 *  return crypt_connection_id of the initialized connection if everything went well.
 */
int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
{
    uint32_t i;
    int id_existing = getcryptconnection_id(c, public_key);

    if (id_existing != -1) {
        IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id_existing].number);

        if (ipport_equal(&c_ip, &ip_port))
            return -1;
    }

    if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1
            || c->crypto_connections == NULL)
        return -1;

    memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection));
    c->crypto_connections[c->crypto_connections_length].number = ~0;

    for (i = 0; i <= c->crypto_connections_length; ++i) {
        if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) {
            int id_new = new_connection(c->lossless_udp, ip_port);

            if (id_new == -1)
                return -1;

            c->crypto_connections[i].number = id_new;
            c->crypto_connections[i].status = CRYPTO_CONN_HANDSHAKE_SENT;
            random_nonce(c->crypto_connections[i].recv_nonce);
            memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
            crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key);
            c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT;

            if (c->crypto_connections_length == i)
                ++c->crypto_connections_length;

            if (send_cryptohandshake(c, id_new, public_key,  c->crypto_connections[i].recv_nonce,
                                     c->crypto_connections[i].sessionpublic_key) == 1) {
                increment_nonce(c->crypto_connections[i].recv_nonce);
                return i;
            }

            return -1; /* This should never happen. */
        }
    }

    return -1;
}
static int send_getnodes(Group_Chat *chat, IP_Port ip_port, int peernum)
{
    if ((uint32_t)peernum >= chat->numpeers)
        return -1;

    if (!is_timeout(chat->group[peernum].last_pinged, PING_TIMEOUT))
        return -1;

    getnodes_data contents;
    contents.pingid = ((uint64_t)random_int() << 32) + random_int();

    chat->group[peernum].last_pinged = unix_time();
    chat->group[peernum].pingid = contents.pingid;

    return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents), 48);
}
Beispiel #25
0
/* Ping all the valid nodes in the toping list every TIME_TOPING seconds.
 * This function must be run at least once every TIME_TOPING seconds.
 */
void do_toping(PING *ping)
{
    if (!is_timeout(ping->last_toping, TIME_TOPING))
        return;

    ping->last_toping = unix_time();
    size_t i;

    for (i = 0; i < MAX_TOPING; ++i) {
        if (!ip_isset(&ping->toping[i].ip_port.ip))
            return;

        send_ping_request(ping, ping->toping[i].ip_port, ping->toping[i].client_id);
        ip_reset(&ping->toping[i].ip_port.ip);
    }
}
/* Callback for DHT ip_port changes. */
static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)
{
    Friend_Connections *fr_c = object;
    Friend_Conn *friend_con = get_conn(fr_c, number);

    if (!friend_con)
        return;

    if (friend_con->crypt_connection_id == -1) {
        friend_new_connection(fr_c, number);
    }

    set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port);
    friend_con->dht_ip_port = ip_port;
    friend_con->dht_ip_port_lastrecv = unix_time();
}
/* Set if friend is online or not.
 * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.
 *
 * is_online 1 means friend is online.
 * is_online 0 means friend is offline
 *
 * return -1 on failure.
 * return 0 on success.
 */
int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online)
{
    if ((uint32_t)friend_num >= onion_c->num_friends)
        return -1;

    if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1)
        onion_c->friends_list[friend_num].last_seen = unix_time();

    onion_c->friends_list[friend_num].is_online = is_online;

    /* This should prevent some clock related issues */
    if (!is_online)
        onion_c->friends_list[friend_num].last_noreplay = 0;

    return 0;
}
Beispiel #28
0
static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port,
                              uint8_t *ping_id)
{
    if (num > onion_c->num_friends)
        return -1;

    Onion_Node *list_nodes = NULL;
    uint8_t *reference_id = NULL;

    if (num == 0) {
        list_nodes = onion_c->clients_announce_list;
        reference_id = onion_c->dht->c->self_public_key;
    } else {
        list_nodes = onion_c->friends_list[num - 1].clients_list;
        reference_id = onion_c->friends_list[num - 1].real_client_id;
    }

    memcpy(cmp_public_key, reference_id, crypto_box_PUBLICKEYBYTES);
    qsort(list_nodes, MAX_ONION_CLIENTS, sizeof(Onion_Node), cmp_entry);

    int index = -1;

    if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
            || id_closest(reference_id, list_nodes[0].client_id, public_key) == 2) {
        index = 0;
    }

    uint32_t i;

    for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
        if (memcmp(list_nodes[i].client_id, public_key, crypto_box_PUBLICKEYBYTES) == 0) {
            index = i;
            break;
        }
    }

    if (index == -1)
        return 0;

    memcpy(list_nodes[index].client_id, public_key, CLIENT_ID_SIZE);
    list_nodes[index].ip_port = ip_port;
    memcpy(list_nodes[index].ping_id, ping_id, ONION_PING_ID_SIZE);
    list_nodes[index].timestamp = unix_time();
    list_nodes[index].last_pinged = 0;
    return 0;
}
static int send_ping(const Friend_Connections *fr_c, int friendcon_id)
{
    Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);

    if (!friend_con)
        return -1;

    uint8_t ping = PACKET_ID_ALIVE;
    int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0);

    if (ret != -1) {
        friend_con->ping_lastsent = unix_time();
        return 0;
    }

    return -1;
}
Beispiel #30
0
Datei: DHT.c Projekt: nypox/nctox
//replace first bad (or empty) node with this one
//return 0 if successfull
//return 1 if not (list contains no bad nodes)
int replace_bad(Client_data * list, uint32_t length, char * client_id, IP_Port ip_port)//tested
{
    uint32_t i;
    uint32_t temp_time = unix_time();
    for(i = 0; i < length; i++)
    {
        if(list[i].timestamp + BAD_NODE_TIMEOUT < temp_time)//if node is bad.
        {
            memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
            list[i].ip_port = ip_port;
            list[i].timestamp = temp_time;
            return 0;
        }
    }
    return 1;
    
}