/* Initialize ID caches */
server->local_list->clients =
- silc_idcache_alloc(0, silc_idlist_client_destructor);
- server->local_list->servers = silc_idcache_alloc(0, NULL);
- server->local_list->channels = silc_idcache_alloc(0, NULL);
+ silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor);
+ server->local_list->servers = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
+ server->local_list->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
/* These are allocated for normal server as well as these hold some
global information that the server has fetched from its router. For
router these are used as they are supposed to be used on router. */
server->global_list->clients =
- silc_idcache_alloc(0, silc_idlist_client_destructor);
- server->global_list->servers = silc_idcache_alloc(0, NULL);
- server->global_list->channels = silc_idcache_alloc(0, NULL);
+ silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor);
+ server->global_list->servers = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
+ server->global_list->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
/* Allocate the entire socket list that is used in server. Eventually
all connections will have entry in this table (it is a table of
server->id = id;
server->id_string = silc_id_id2str(id, SILC_ID_SERVER);
- server->id_string_len = silc_id_get_len(SILC_ID_SERVER);
+ server->id_string_len = silc_id_get_len(id, SILC_ID_SERVER);
server->id_type = SILC_ID_SERVER;
server->server_name = server->config->server_info->server_name;
&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. */
SilcBuffer packet;
SilcServerHBContext hb_context;
unsigned char *id_string;
+ uint32 id_len;
SilcIDListData idata;
SILC_LOG_DEBUG(("Start"));
/* Send NEW_SERVER packet to the router. We will become registered
to the SILC network after sending this packet. */
id_string = silc_id_id2str(server->id, SILC_ID_SERVER);
- packet = silc_buffer_alloc(2 + 2 + SILC_ID_SERVER_LEN +
- strlen(server->server_name));
+ id_len = silc_id_get_len(server->id, SILC_ID_SERVER);
+ packet = silc_buffer_alloc(2 + 2 + id_len + strlen(server->server_name));
silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
silc_buffer_format(packet,
- SILC_STR_UI_SHORT(SILC_ID_SERVER_LEN),
- SILC_STR_UI_XNSTRING(id_string, SILC_ID_SERVER_LEN),
+ SILC_STR_UI_SHORT(id_len),
+ SILC_STR_UI_XNSTRING(id_string, id_len),
SILC_STR_UI_SHORT(strlen(server->server_name)),
SILC_STR_UI_XNSTRING(server->server_name,
strlen(server->server_name)),
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);
and other information is created after we have received NEW_CLIENT
packet from client. */
client = silc_idlist_add_client(server->local_list,
- NULL, 0, NULL, NULL, NULL, NULL, sock);
+ NULL, NULL, NULL, NULL, NULL, sock);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to cache"));
silc_free(sock->user_data);
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)) {
+ memcmp(packet->dst_id, server->id_string, packet->dst_id_len)) {
/* Route the packet to fastest route for the destination ID */
void *id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
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);
if (notify && !server->standalone && server->router)
silc_server_send_notify_signoff(server, server->router->connection,
server->server_type == SILC_SERVER ?
- FALSE : TRUE, client->id,
- SILC_ID_CLIENT_LEN, signoff);
+ FALSE : TRUE, client->id, signoff);
/* Remove client from all channels */
if (notify)
/* 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. */
silc_buffer_free(idp);
}
- if (silc_idcache_find_by_id(server->local_list->clients,
- SILC_ID_CACHE_ANY, SILC_ID_CLIENT, &list)) {
+ if (silc_idcache_get_all(server->local_list->clients, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
silc_idcache_list_free(list);
}
- if (silc_idcache_find_by_id(server->global_list->clients,
- SILC_ID_CACHE_ANY, SILC_ID_CLIENT, &list)) {
+ if (silc_idcache_get_all(server->global_list->clients, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
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;
}
to our primary route. */
if (broadcast && server->standalone == FALSE)
silc_server_send_new_channel(server, server->router->connection, TRUE,
- channel_name, entry->id, SILC_ID_CHANNEL_LEN,
+ channel_name, entry->id,
+ silc_id_get_len(entry->id, SILC_ID_CHANNEL),
entry->mode);
server->stat.my_channels++;
to our primary route. */
if (broadcast && server->standalone == FALSE)
silc_server_send_new_channel(server, server->router->connection, TRUE,
- channel_name, entry->id, SILC_ID_CHANNEL_LEN,
+ channel_name, entry->id,
+ silc_id_get_len(entry->id, SILC_ID_CHANNEL),
entry->mode);
server->stat.my_channels++;
SilcBuffer idp;
/* Go through all clients in the list */
- if (silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
- SILC_ID_SERVER, &list)) {
+ if (silc_idcache_get_all(id_list->servers, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
entry = (SilcServerEntry)id_cache->context;
SilcBuffer idp;
/* Go through all clients in the list */
- if (silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
- SILC_ID_CLIENT, &list)) {
+ if (silc_idcache_get_all(id_list->clients, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
client = (SilcClientEntry)id_cache->context;
}
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;
SilcChannelEntry channel;
unsigned char *cid;
+ uint32 id_len;
uint16 name_len;
int len;
SILC_LOG_DEBUG(("Start"));
/* Go through all channels in the list */
- if (silc_idcache_find_by_id(id_list->channels, SILC_ID_CACHE_ANY,
- SILC_ID_CHANNEL, &list)) {
+ if (silc_idcache_get_all(id_list->channels, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
channel = (SilcChannelEntry)id_cache->context;
cid = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
+ id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
name_len = strlen(channel->channel_name);
- len = 4 + name_len + SILC_ID_CHANNEL_LEN + 4;
+ len = 4 + name_len + id_len + 4;
*channels =
silc_buffer_realloc(*channels,
(*channels ? (*channels)->truelen + len : len));
SILC_STR_UI_SHORT(name_len),
SILC_STR_UI_XNSTRING(channel->channel_name,
name_len),
- SILC_STR_UI_SHORT(SILC_ID_CHANNEL_LEN),
- SILC_STR_UI_XNSTRING(cid, SILC_ID_CHANNEL_LEN),
+ SILC_STR_UI_SHORT(id_len),
+ SILC_STR_UI_XNSTRING(cid, id_len),
SILC_STR_UI_INT(channel->mode),
SILC_STR_END);
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
SilcBuffer idp;
uint32 list_count = 0;
+ /* XXX rewrite - this does not support IPv6 based Client ID's. */
+
client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
silc_list_count(channel->user_list));
client_mode_list = silc_buffer_alloc(4 *
SILC_GET32_MSB(mode, mode_list->data);
silc_buffer_pull(mode_list, 4);
- if (noadd && !SILC_ID_CLIENT_COMPARE(client_id, noadd)) {
+ if (noadd && SILC_ID_CLIENT_COMPARE(client_id, noadd)) {
silc_free(client_id);
continue;
}
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
- client = silc_idlist_add_client(server->global_list, NULL, 0, NULL,
- NULL,
+ client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
silc_id_dup(client_id, SILC_ID_CLIENT),
sock->user_data, NULL);
if (!client) {
SilcChannelEntry channel;
SilcChannelClientEntry chl;
unsigned char *cid;
+ uint32 id_len;
uint16 name_len;
int len;
continue;
cid = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
+ id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
name_len = strlen(channel->channel_name);
- len = 4 + name_len + SILC_ID_CHANNEL_LEN + 4;
+ len = 4 + name_len + id_len + 4;
buffer = silc_buffer_realloc(buffer,
(buffer ? (buffer)->truelen + len : len));
silc_buffer_pull_tail(buffer, ((buffer)->end - (buffer)->data));
SILC_STR_UI_SHORT(name_len),
SILC_STR_UI_XNSTRING(channel->channel_name,
name_len),
- SILC_STR_UI_SHORT(SILC_ID_CHANNEL_LEN),
- SILC_STR_UI_XNSTRING(cid, SILC_ID_CHANNEL_LEN),
+ SILC_STR_UI_SHORT(id_len),
+ SILC_STR_UI_XNSTRING(cid, id_len),
SILC_STR_UI_INT(chl->mode), /* Client's mode */
SILC_STR_END);
silc_buffer_pull(buffer, len);
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;