&newsocket);
server->sockets[sock[i]] = newsocket;
+
+ /* Perform name and address lookups to resolve the listenning address
+ and port. */
+ if (!silc_net_check_local_by_sock(sock[i], &newsocket->hostname,
+ &newsocket->ip)) {
+ if ((server->params->require_reverse_mapping && !newsocket->hostname) ||
+ !newsocket->ip) {
+ SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
+ newsocket->hostname ? newsocket->hostname :
+ newsocket->ip ? newsocket->ip : ""));
+ server->stat.conn_failures++;
+ goto err0;
+ }
+ if (!newsocket->hostname)
+ newsocket->hostname = strdup(newsocket->ip);
+ }
+ newsocket->port = silc_net_get_local_port(sock[i]);
/* Put the allocated socket pointer also to the entry allocated above
for fast back-referencing to the socket list. */
SilcServer server = (SilcServer)context;
SilcSocketConnection newsocket;
SilcServerKEInternalContext *proto_ctx;
- int sock;
+ int sock, port;
+ void *cconfig, *sconfig, *rconfig;
+ SilcServerConfigSectionDenyConnection *deny;
SILC_LOG_DEBUG(("Accepting new connection"));
}
newsocket->port = silc_net_get_remote_port(sock);
+ /* Register the connection for network input and output. This sets
+ that scheduler will listen for incoming packets for this connection
+ and sets that outgoing packets may be sent to this connection as well.
+ However, this doesn't set the scheduler for outgoing traffic, it
+ will be set separately by calling SILC_SET_CONNECTION_FOR_OUTPUT,
+ later when outgoing data is available. */
+ SILC_REGISTER_CONNECTION_FOR_IO(sock);
+
+ port = server->sockets[fd]->port; /* Listenning port */
+
+ /* Check whether this connection is denied to connect to us. */
+ deny = silc_server_config_denied_conn(server->config, newsocket->ip, port);
+ if (!deny)
+ deny = silc_server_config_denied_conn(server->config, newsocket->hostname,
+ port);
+ if (deny) {
+ /* The connection is denied */
+ silc_server_disconnect_remote(server, newsocket, deny->comment ?
+ deny->comment :
+ "Server closed connection: "
+ "Connection refused");
+ server->stat.conn_failures++;
+ return;
+ }
+
+ /* Check whether we have configred this sort of connection at all. We
+ have to check all configurations since we don't know what type of
+ connection this is. */
+ if (!(cconfig = silc_server_config_find_client_conn(server->config,
+ newsocket->ip, port)))
+ cconfig = silc_server_config_find_client_conn(server->config,
+ newsocket->hostname,
+ port);
+ if (!(sconfig = silc_server_config_find_server_conn(server->config,
+ newsocket->ip,
+ port)))
+ sconfig = silc_server_config_find_server_conn(server->config,
+ newsocket->hostname,
+ port);
+ if (!(rconfig = silc_server_config_find_router_conn(server->config,
+ newsocket->ip, port)))
+ rconfig = silc_server_config_find_router_conn(server->config,
+ newsocket->hostname,
+ port);
+ if (!cconfig && !sconfig && !rconfig) {
+ silc_server_disconnect_remote(server, newsocket,
+ "Server closed connection: "
+ "Connection refused");
+ server->stat.conn_failures++;
+ return;
+ }
+
+ /* The connection is allowed */
+
SILC_LOG_INFO(("Incoming connection from %s (%s)", newsocket->hostname,
newsocket->ip));
proto_ctx->sock = newsocket;
proto_ctx->rng = server->rng;
proto_ctx->responder = TRUE;
+ proto_ctx->cconfig = cconfig;
+ proto_ctx->sconfig = sconfig;
+ proto_ctx->rconfig = rconfig;
/* Prepare the connection for key exchange protocol. We allocate the
protocol but will not start it yet. The connector will be the
context, 60, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_LOW);
-
- /* Register the connection for network input and output. This sets
- that scheduler will listen for incoming packets for this connection
- and sets that outgoing packets may be sent to this connection as well.
- However, this doesn't set the scheduler for outgoing traffic, it
- will be set separately by calling SILC_SET_CONNECTION_FOR_OUTPUT,
- later when outgoing data is available. */
- SILC_REGISTER_CONNECTION_FOR_IO(sock);
}
/* Second part of accepting new connection. Key exchange protocol has been
proto_ctx->responder = TRUE;
proto_ctx->dest_id_type = ctx->dest_id_type;
proto_ctx->dest_id = ctx->dest_id;
+ proto_ctx->cconfig = ctx->cconfig;
+ proto_ctx->sconfig = ctx->sconfig;
+ proto_ctx->rconfig = ctx->rconfig;
/* Free old protocol as it is finished now */
silc_protocol_free(protocol);
case SILC_SOCKET_TYPE_ROUTER:
{
SilcServerEntry new_server;
+ SilcServerConfigSectionServerConnection *conn =
+ sock->type == SILC_SOCKET_TYPE_SERVER ? ctx->sconfig : ctx->rconfig;
SILC_LOG_DEBUG(("Remote host is %s",
sock->type == SILC_SOCKET_TYPE_SERVER ?
server->stat.servers++;
id_entry = (void *)new_server;
-
- /* There is connection to other server now, if it is router then
- we will have connection to outside world. If we are router but
- normal server connected to us then we will remain standalone,
- if we are standlone. */
+
+ /* Check whether this connection is to be our primary router connection
+ if we dont' already have the primary route. */
if (server->standalone && sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ if (silc_server_config_is_primary_route(server->config) &&
+ !conn->initiator)
+ break;
+
SILC_LOG_DEBUG(("We are not standalone server anymore"));
server->standalone = FALSE;
if (!server->id_entry->router) {
server->router = id_entry;
}
}
+
break;
}
default:
if (client && client->id) {
void *id = silc_id_str2id(packet->src_id, packet->src_id_len,
packet->src_id_type);
- if (SILC_ID_CLIENT_COMPARE(client->id, id)) {
+ if (!id || SILC_ID_CLIENT_COMPARE(client->id, id)) {
silc_free(id);
goto out;
}
if (server->server_type == SILC_ROUTER) {
/* Route the packet if it is not destined to us. Other ID types but
server are handled separately after processing them. */
- if (packet->dst_id_type == SILC_ID_SERVER &&
+ if (!(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
+ packet->dst_id_type == SILC_ID_SERVER &&
sock->type != SILC_SOCKET_TYPE_CLIENT &&
SILC_ID_SERVER_COMPARE(packet->dst_id, server->id_string)) {
silc_free(id);
goto out;
}
-
+ }
+
+ /* Parse the incoming packet type */
+ silc_server_packet_parse_type(server, sock, packet);
+
+ if (server->server_type == SILC_ROUTER) {
/* Broadcast packet if it is marked as broadcast packet and it is
originated from router and we are router. */
if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
- packet->flags & SILC_PACKET_FLAG_BROADCAST) {
+ packet->flags & SILC_PACKET_FLAG_BROADCAST &&
+ !server->standalone) {
silc_server_packet_broadcast(server, server->router->connection, packet);
}
}
- /* Parse the incoming packet type */
- silc_server_packet_parse_type(server, sock, packet);
-
out:
/* silc_buffer_clear(sock->inbuf); */
silc_packet_context_free(packet);
switch (sock->type) {
case SILC_SOCKET_TYPE_UNKNOWN:
+ case SILC_SOCKET_TYPE_CLIENT:
/* Parse the packet with timeout */
silc_task_register(server->timeout_queue, sock->sock,
silc_server_packet_parse_real,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
break;
- case SILC_SOCKET_TYPE_CLIENT:
- /* Parse the packet with timeout (unless protocol is active) */
-
- /* If REKEY protocol is active we must proccess the packets synchronously
- since we must assure that incoming packets that are encrypted with
- the old key is processed before the new keys is set to use. */
- if (SILC_SERVER_IS_REKEY(sock))
- silc_server_packet_parse_real(server->timeout_queue, SILC_TASK_READ,
- (void *)parser_context, sock->sock);
- else
- silc_task_register(server->timeout_queue, sock->sock,
- silc_server_packet_parse_real,
- (void *)parser_context, 0,
- (sock->protocol ? 1 : 100000),
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- break;
case SILC_SOCKET_TYPE_SERVER:
case SILC_SOCKET_TYPE_ROUTER:
/* Packets from servers are parsed as soon as possible */
-
- /* If REKEY protocol is active we must proccess the packets synchronously
- since we must assure that incoming packets that are encrypted with
- the old key is processed before the new keys is set to use. */
- if (SILC_SERVER_IS_REKEY(sock))
- silc_server_packet_parse_real(server->timeout_queue, SILC_TASK_READ,
- (void *)parser_context, sock->sock);
- else
- silc_task_register(server->timeout_queue, sock->sock,
- silc_server_packet_parse_real,
- (void *)parser_context, 0, 1,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
+ silc_task_register(server->timeout_queue, sock->sock,
+ silc_server_packet_parse_real,
+ (void *)parser_context, 0, 1,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
break;
default:
return;
/* Free all client entries that this server owns as they will
become invalid now as well. */
- silc_server_remove_clients_by_server(server, user_data, TRUE);
+ if (user_data->id)
+ silc_server_remove_clients_by_server(server, user_data, TRUE);
/* If this was our primary router connection then we're lost to
the outside world. */
argv_types);
silc_server_send_notify_args(server,
server->router->connection,
- server->server_type ==
- SILC_SERVER ? FALSE : TRUE,
+ server->server_type == SILC_SERVER ?
+ FALSE : TRUE,
SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
argc, args);
silc_buffer_free(args);
signoff_message, signoff_message ?
strlen(signoff_message) : 0);
- server->stat.my_channels--;
-
if (channel->rekey)
silc_task_unregister_by_context(server->timeout_queue, channel->rekey);
if (!silc_idlist_del_channel(server->local_list, channel))
silc_idlist_del_channel(server->global_list, channel);
+ server->stat.my_channels--;
continue;
}
SILC_NOTIFY_TYPE_LEAVE, 1,
clidp->data, clidp->len);
- server->stat.my_channels--;
silc_buffer_free(clidp);
if (channel->rekey)
if (!silc_idlist_del_channel(server->local_list, channel))
silc_idlist_del_channel(server->global_list, channel);
+ server->stat.my_channels--;
return FALSE;
}
}
static SilcBuffer
-silc_server_announce_encode_join(uint32 argc, ...)
+silc_server_announce_encode_notify(SilcNotifyType notify, uint32 argc, ...)
{
va_list ap;
va_start(ap, argc);
- return silc_notify_payload_encode(SILC_NOTIFY_TYPE_JOIN, argc, ap);
+ return silc_notify_payload_encode(notify, argc, ap);
}
/* Returns assembled packets for channel users of the `channel'. */
void silc_server_announce_get_channel_users(SilcServer server,
SilcChannelEntry channel,
- SilcBuffer *channel_users)
+ SilcBuffer *channel_users,
+ SilcBuffer *channel_users_modes)
{
SilcChannelClientEntry chl;
SilcBuffer chidp, clidp;
SilcBuffer tmp;
int len;
+ unsigned char mode[4];
SILC_LOG_DEBUG(("Start"));
silc_list_start(channel->user_list);
while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
clidp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
- tmp = silc_server_announce_encode_join(2, clidp->data, clidp->len,
- chidp->data, chidp->len);
+
+ /* JOIN Notify */
+ tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_JOIN, 2,
+ clidp->data, clidp->len,
+ chidp->data, chidp->len);
len = tmp->len;
*channel_users =
silc_buffer_realloc(*channel_users,
silc_buffer_put(*channel_users, tmp->data, tmp->len);
silc_buffer_pull(*channel_users, len);
- silc_buffer_free(clidp);
silc_buffer_free(tmp);
+
+ /* CUMODE notify for mode change on the channel */
+ SILC_PUT32_MSB(chl->mode, mode);
+ tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CUMODE_CHANGE,
+ 3, clidp->data, clidp->len,
+ mode, 4,
+ clidp->data, clidp->len);
+ len = tmp->len;
+ *channel_users_modes =
+ silc_buffer_realloc(*channel_users_modes,
+ (*channel_users_modes ?
+ (*channel_users_modes)->truelen + len : len));
+ silc_buffer_pull_tail(*channel_users_modes,
+ ((*channel_users_modes)->end -
+ (*channel_users_modes)->data));
+
+ silc_buffer_put(*channel_users_modes, tmp->data, tmp->len);
+ silc_buffer_pull(*channel_users_modes, len);
+ silc_buffer_free(tmp);
+
+ silc_buffer_free(clidp);
}
silc_buffer_free(chidp);
}
void silc_server_announce_get_channels(SilcServer server,
SilcIDList id_list,
SilcBuffer *channels,
- SilcBuffer *channel_users)
+ SilcBuffer *channel_users,
+ SilcBuffer *channel_users_modes)
{
SilcIDCacheList list;
SilcIDCacheEntry id_cache;
silc_buffer_pull(*channels, len);
silc_server_announce_get_channel_users(server, channel,
- channel_users);
+ channel_users,
+ channel_users_modes);
silc_free(cid);
void silc_server_announce_channels(SilcServer server)
{
- SilcBuffer channels = NULL, channel_users = NULL;
+ SilcBuffer channels = NULL, channel_users = NULL, channel_users_modes = NULL;
SILC_LOG_DEBUG(("Announcing channels and channel users"));
/* Get channels and channel users in local list */
silc_server_announce_get_channels(server, server->local_list,
- &channels, &channel_users);
+ &channels, &channel_users,
+ &channel_users_modes);
/* Get channels and channel users in global list */
silc_server_announce_get_channels(server, server->global_list,
- &channels, &channel_users);
+ &channels, &channel_users,
+ &channel_users_modes);
if (channels) {
silc_buffer_push(channels, channels->data - channels->head);
silc_buffer_free(channel_users);
}
+
+ if (channel_users_modes) {
+ silc_buffer_push(channel_users_modes,
+ channel_users_modes->data - channel_users_modes->head);
+ SILC_LOG_HEXDUMP(("channel users modes"), channel_users_modes->data,
+ channel_users_modes->len);
+
+ /* Send the packet */
+ silc_server_packet_send(server, server->router->connection,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ channel_users_modes->data,
+ channel_users_modes->len,
+ FALSE);
+
+ silc_buffer_free(channel_users_modes);
+ }
}
/* Failure timeout callback. If this is called then we will immediately
return;
}
-#if 0
- /* Take the keys into use */
- if (ctx->pfs == TRUE)
- silc_server_protocol_rekey_generate_pfs(server, ctx);
- else
- silc_server_protocol_rekey_generate(server, ctx);
-#endif
-
/* Cleanup */
silc_protocol_free(protocol);
sock->protocol = NULL;