}
}
+/* Adds listener socket to the listener sockets table. This function is
+ used to add socket objects that are listeners to the client. This should
+ not be used to add other connection objects. */
+
+void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
+{
+ int i;
+
+ if (!client->sockets) {
+ client->sockets = silc_calloc(1, sizeof(*client->sockets));
+ client->sockets[0] = sock;
+ client->sockets_count = 1;
+ return;
+ }
+
+ for (i = 0; i < client->sockets_count; i++) {
+ if (client->sockets[i] == NULL) {
+ client->sockets[i] = sock;
+ return;
+ }
+ }
+
+ client->sockets = silc_realloc(client->sockets, sizeof(*client->sockets) *
+ (client->sockets_count + 1));
+ client->sockets[client->sockets_count] = sock;
+ client->sockets_count++;
+}
+
+/* Deletes listener socket from the listener sockets table. */
+
+void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
+{
+ int i;
+
+ if (!client->sockets)
+ return;
+
+ for (i = 0; i < client->sockets_count; i++) {
+ if (client->sockets[i] == sock) {
+ client->sockets[i] = NULL;
+ return;
+ }
+ }
+}
+
static int
silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
{
if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
sock->port, &proto_ctx->auth_meth,
&proto_ctx->auth_data,
- &proto_ctx->auth_data_len))
- {
- /* XXX do AUTH_REQUEST resolcing with server */
- proto_ctx->auth_meth = SILC_AUTH_NONE;
- }
+ &proto_ctx->auth_data_len)) {
+ client->ops->say(client, ctx->sock->user_data,
+ "Could not resolve authentication method to use, "
+ "assume no authentication");
+ proto_ctx->auth_meth = SILC_AUTH_NONE;
+ }
/* Free old protocol as it is finished now */
silc_protocol_free(protocol);
if (ctx->packet)
silc_packet_context_free(ctx->packet);
silc_free(ctx);
- /* silc_free(ctx->keymat....); */
sock->protocol = NULL;
/* Allocate the authentication protocol. This is allocated here
/* If connection is disconnecting already we will finally
close the connection */
if (SILC_IS_DISCONNECTING(sock)) {
- client->ops->disconnect(client, conn);
- silc_client_close_connection(client, conn);
+ if (sock == conn->sock)
+ client->ops->disconnect(client, conn);
+ silc_client_close_connection(client, sock, conn);
return;
}
SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
- client->ops->disconnect(client, conn);
- silc_client_close_connection(client, conn);
+ if (sock == conn->sock)
+ client->ops->disconnect(client, conn);
+ silc_client_close_connection(client, sock, conn);
return;
}
/* Process the packet. This will call the parser that will then
decrypt and parse the packet. */
- silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
- silc_client_packet_parse, client);
+ if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
+ silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
+ silc_client_packet_parse, client);
+ else
+ silc_packet_receive_process(sock, NULL, NULL,
+ silc_client_packet_parse, client);
}
}
all other packets are special packets
*/
- if ((packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
- !(buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY)) ||
- packet_type != SILC_PACKET_CHANNEL_MESSAGE)
+
+ if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
+ (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
+ return FALSE;
+
+ if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
return TRUE;
return FALSE;
SILC_LOG_DEBUG(("Start"));
/* Decrypt the received packet */
- ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet,
- silc_client_packet_decrypt_check, parse_ctx);
+ if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
+ ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet,
+ silc_client_packet_decrypt_check, parse_ctx);
+ else
+ ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
+ silc_client_packet_decrypt_check, parse_ctx);
+
if (ret < 0)
goto out;
silc_client_packet_parse_type(client, sock, packet);
out:
- silc_buffer_clear(sock->inbuf);
+ /* silc_buffer_clear(sock->inbuf); */
silc_packet_context_free(packet);
silc_free(parse_ctx);
}
break;
case SILC_PACKET_KEY_EXCHANGE:
- if (sock->protocol) {
+ if (sock->protocol && sock->protocol->protocol &&
+ sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
SilcClientKEInternalContext *proto_ctx =
(SilcClientKEInternalContext *)sock->protocol->context;
break;
case SILC_PACKET_KEY_EXCHANGE_1:
- if (sock->protocol) {
+ if (sock->protocol && sock->protocol->protocol &&
+ sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
+ SilcClientKEInternalContext *proto_ctx =
+ (SilcClientKEInternalContext *)sock->protocol->context;
+
+ if (proto_ctx->packet)
+ silc_packet_context_free(proto_ctx->packet);
+
+ proto_ctx->packet = silc_packet_context_dup(packet);
+ proto_ctx->dest_id_type = packet->src_id_type;
+ proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
+ packet->src_id_type);
+ if (!proto_ctx->dest_id)
+ break;
+ /* Let the protocol handle the packet */
+ sock->protocol->execute(client->timeout_queue, 0,
+ sock->protocol, sock->sock, 0, 0);
} else {
SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
"protocol active, packet dropped."));
}
break;
case SILC_PACKET_KEY_EXCHANGE_2:
- if (sock->protocol) {
+ if (sock->protocol && sock->protocol->protocol &&
+ sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
SilcClientKEInternalContext *proto_ctx =
(SilcClientKEInternalContext *)sock->protocol->context;
/* Set the packet context pointers */
packetdata.flags = 0;
packetdata.type = type;
- if (((SilcClientConnection)sock->user_data)->local_id_data)
+ if (sock->user_data &&
+ ((SilcClientConnection)sock->user_data)->local_id_data)
packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
else
packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
}
/* Closes connection to remote end. Free's all allocated data except
- for some information such as nickname etc. that are valid at all time. */
+ for some information such as nickname etc. that are valid at all time.
+ If the `sock' is NULL then the conn->sock will be used. If `sock' is
+ provided it will be checked whether the sock and `conn->sock' are the
+ same (they can be different, ie. a socket can use `conn' as its
+ connection but `conn->sock' might be actually a different connection
+ than the `sock'). */
void silc_client_close_connection(SilcClient client,
+ SilcSocketConnection sock,
SilcClientConnection conn)
{
- SilcSocketConnection sock = conn->sock;
+ int del = FALSE;
+
+ if (!sock || (sock && conn->sock == sock))
+ del = TRUE;
+ if (!sock)
+ sock = conn->sock;
/* We won't listen for this connection anymore */
silc_schedule_unset_listen_fd(sock->sock);
/* Close the actual connection */
silc_net_close_connection(sock->sock);
- client->ops->say(client, sock->user_data,
- "Closed connection to host %s", sock->hostname);
-
/* Free everything */
- if (sock->user_data) {
+ if (del && sock->user_data) {
/* XXX Free all client entries and channel entries. */
+ client->ops->say(client, sock->user_data,
+ "Closed connection to host %s", sock->hostname);
+
/* Clear ID caches */
silc_idcache_del_all(conn->client_cache);
silc_idcache_del_all(conn->channel_cache);
silc_free(msg);
SILC_SET_DISCONNECTED(sock);
- silc_client_close_connection(client, sock->user_data);
+ silc_client_close_connection(client, sock, sock->user_data);
}
/* Received error message from server. Display it on the screen.
/* Parses mode mask and returns the mode as string. */
-char *silc_client_chmode(unsigned int mode)
+char *silc_client_chmode(unsigned int mode, SilcChannelEntry channel)
{
- char string[20];
+ char string[100];
if (!mode)
return NULL;
if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
strncat(string, "a", 1);
+ if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
+ strncat(string, "f", 1);
+
+ if (mode & SILC_CHANNEL_MODE_CIPHER) {
+ char cipher[30];
+ memset(cipher, 0, sizeof(cipher));
+ snprintf(cipher, sizeof(cipher), " c (%s)",
+ channel->channel_key->cipher->name);
+ strncat(string, cipher, strlen(cipher));
+ }
+
+ if (mode & SILC_CHANNEL_MODE_HMAC) {
+ char hmac[30];
+ memset(hmac, 0, sizeof(hmac));
+ snprintf(hmac, sizeof(hmac), " h (%s)",
+ channel->hmac->hmac->name);
+ strncat(string, hmac, strlen(hmac));
+ }
+
/* Rest of mode is ignored */
return strdup(string);