silc_free(sconn);
silc_schedule_task_del_by_callback(server->schedule,
silc_server_failure_callback);
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Key exchange failed");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
return;
}
silc_free(sconn);
silc_schedule_task_del_by_callback(server->schedule,
silc_server_failure_callback);
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Key exchange failed");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
return;
}
silc_ske_free_key_material(ctx->keymat);
silc_free(sconn);
silc_schedule_task_del_by_callback(server->schedule,
silc_server_failure_callback);
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Key exchange failed");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
return;
}
protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
/* Error occured during protocol */
silc_free(ctx->dest_id);
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Authentication failed");
+ silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED,
+ NULL);
goto out;
}
if (!id_entry) {
silc_free(ctx->dest_id);
SILC_LOG_ERROR(("Cannot add new server entry to cache"));
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Authentication failed");
+ silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED,
+ NULL);
goto out;
}
sock->ip ? sock->ip : ""));
server->stat.conn_failures++;
silc_server_disconnect_remote(server, sock,
- "Server closed connection: Unknown host");
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ "Unknown host or IP");
return;
}
/* The connection is denied */
SILC_LOG_INFO(("Connection %s (%s) is denied",
sock->hostname, sock->ip));
- silc_server_disconnect_remote(server, sock, deny->reason ?
- deny->reason :
- "Server closed connection: "
- "Connection refused");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_BANNED_FROM_SERVER,
+ deny->reason);
server->stat.conn_failures++;
return;
}
SILC_LOG_INFO(("Connection %s (%s) is not allowed", sock->hostname,
sock->ip));
silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Connection refused");
+ SILC_STATUS_ERR_BANNED_FROM_SERVER);
server->stat.conn_failures++;
return;
}
silc_free(ctx);
silc_schedule_task_del_by_callback(server->schedule,
silc_server_failure_callback);
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Key exchange failed");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED,
+ NULL);
server->stat.auth_failures++;
return;
}
silc_free(ctx);
silc_schedule_task_del_by_callback(server->schedule,
silc_server_failure_callback);
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Key exchange failed");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
server->stat.auth_failures++;
return;
}
silc_free(ctx);
silc_schedule_task_del_by_callback(server->schedule,
silc_server_failure_callback);
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
- "Authentication failed");
+ silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED,
+ NULL);
server->stat.auth_failures++;
return;
}
if (!client) {
SILC_LOG_ERROR(("Could not add new client to cache"));
silc_free(sock->user_data);
- silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Authentication failed");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_AUTH_FAILED, NULL);
server->stat.auth_failures++;
goto out;
}
if (!new_server) {
SILC_LOG_ERROR(("Could not add new server to cache"));
silc_free(sock->user_data);
- silc_server_disconnect_remote(server, sock,
- "Server closed connection: "
- "Authentication failed");
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_AUTH_FAILED, NULL);
server->stat.auth_failures++;
goto out;
}
/* Parse the packet type */
switch (type) {
case SILC_PACKET_DISCONNECT:
- SILC_LOG_DEBUG(("Disconnect packet"));
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- if (silc_string_is_ascii(packet->buffer->data, packet->buffer->len)) {
- /* Duplicate to null terminate the string. */
- char *message = silc_memdup(packet->buffer->data, packet->buffer->len);
- SILC_LOG_ERROR(("%s", message));
+ {
+ SilcStatus status;
+ char *message = NULL;
+
+ SILC_LOG_DEBUG(("Disconnect packet"));
+
+ if (packet->flags & SILC_PACKET_FLAG_LIST)
+ break;
+ if (packet->buffer->len < 1)
+ break;
+
+ status = (SilcStatus)packet->buffer->data[0];
+ if (packet->buffer->len > 1 &&
+ silc_utf8_valid(packet->buffer->data + 1, packet->buffer->len - 1))
+ message = silc_memdup(packet->buffer->data, packet->buffer->len);
+
+ SILC_LOG_ERROR(("Disconnected by %s (%s): %s (%d) %s",
+ sock->ip, sock->hostname,
+ silc_get_status_message(status), status,
+ message ? message : ""));
silc_free(message);
}
break;
void silc_server_disconnect_remote(SilcServer server,
SilcSocketConnection sock,
- const char *fmt, ...)
+ SilcStatus status, ...)
{
va_list ap;
- unsigned char buf[4096];
+ unsigned char buf[512];
+ SilcBuffer buffer;
+ char *cp;
+ int len;
if (!sock)
return;
memset(buf, 0, sizeof(buf));
- va_start(ap, fmt);
- vsprintf(buf, fmt, ap);
+ va_start(ap, status);
+ cp = va_arg(ap, char *);
+ if (cp) {
+ vsnprintf(buf, sizeof(buf) - 1, cp, ap);
+ cp = buf;
+ }
va_end(ap);
SILC_LOG_DEBUG(("Disconnecting remote host"));
/* Notify remote end that the conversation is over. The notify message
is tried to be sent immediately. */
+
+ len = 1;
+ if (cp)
+ len += silc_utf8_encoded_len(buf, strlen(buf), SILC_STRING_ASCII);
+
+ buffer = silc_buffer_alloc_size(len);
+ if (!buffer)
+ goto out;
+
+ buffer->data[0] = status;
+ if (cp)
+ silc_utf8_encode(buf, strlen(buf), SILC_STRING_ASCII, buffer->data + 1,
+ buffer->len - 1);
silc_server_packet_send(server, sock, SILC_PACKET_DISCONNECT, 0,
- buf, strlen(buf), TRUE);
+ buffer->data, buffer->len, TRUE);
+ silc_buffer_free(buffer);
+
+ out:
silc_server_packet_queue_purge(server, sock);
/* Mark the connection to be disconnected */
{
SilcServer server = (SilcServer)context;
SilcSocketConnection sock = server->sockets[fd];
+ SilcProtocolType protocol = 0;
SILC_LOG_DEBUG(("Start"));
/* If we have protocol active we must assure that we call the protocol's
final callback so that all the memory is freed. */
if (sock->protocol) {
+ protocol = sock->protocol->protocol->type;
silc_protocol_cancel(sock->protocol, server->schedule);
sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_protocol_execute_final(sock->protocol, server->schedule);
if (sock->user_data)
silc_server_free_sock_user_data(server, sock, NULL);
- silc_server_disconnect_remote(server, sock, "Server closed connection: "
+ silc_server_disconnect_remote(server, sock,
+ protocol ==
+ SILC_PROTOCOL_SERVER_CONNECTION_AUTH ?
+ SILC_STATUS_ERR_AUTH_FAILED :
+ SILC_STATUS_ERR_KEY_EXCHANGE_FAILED,
"Connection timeout");
}