we will send the packet to that server. */
router = (SilcServerEntry)dst_sock->user_data;
idata = (SilcIDListData)router;
- //assert(client->router == server->id_entry);
silc_server_send_private_message(server, dst_sock,
idata->send_key,
/* Distribute the key to everybody who is on the channel. If we are router
we will also send it to locally connected servers. */
- silc_server_send_channel_key(server, channel, FALSE);
+ silc_server_send_channel_key(server, sock, channel, FALSE);
}
/* Received packet to replace a ID. This checks that the requested ID
we will broadcast it. The sending socket really cannot be router or
the router is buggy. If this packet is coming from router then it must
have the broadcast flag set already and we won't do anything. */
- if (server->server_type == SILC_ROUTER &&
+ if (!server->standalone && server->server_type == SILC_ROUTER &&
sock->type == SILC_SOCKET_TYPE_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received Replace ID packet"));
/* Replace the old ID */
switch(old_id_type) {
case SILC_ID_CLIENT:
- SILC_LOG_DEBUG(("Old Client ID id(%s)",
- silc_id_render(id, SILC_ID_CLIENT)));
- SILC_LOG_DEBUG(("New Client ID id(%s)",
- silc_id_render(id2, SILC_ID_CLIENT)));
- if (silc_idlist_replace_client_id(server->local_list, id, id2) == NULL)
- if (server->server_type == SILC_ROUTER)
- silc_idlist_replace_client_id(server->global_list, id, id2);
- break;
+ {
+ SilcBuffer nidp, oidp;
+ SilcClientEntry client = NULL;
+
+ SILC_LOG_DEBUG(("Old Client ID id(%s)",
+ silc_id_render(id, SILC_ID_CLIENT)));
+ SILC_LOG_DEBUG(("New Client ID id(%s)",
+ silc_id_render(id2, SILC_ID_CLIENT)));
+
+ if ((client = silc_idlist_replace_client_id(server->local_list,
+ id, id2)) == NULL)
+ if (server->server_type == SILC_ROUTER)
+ client = silc_idlist_replace_client_id(server->global_list, id, id2);
+
+ if (client) {
+ oidp = silc_id_payload_encode(id, SILC_ID_CLIENT);
+ nidp = silc_id_payload_encode(id2, SILC_ID_CLIENT);
+
+ /* Send the NICK_CHANGE notify type to local clients on the channels
+ this client is joined to. */
+ silc_server_send_notify_on_channels(server, client,
+ SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
+ oidp->data, oidp->len,
+ nidp->data, nidp->len);
+
+ silc_buffer_free(nidp);
+ silc_buffer_free(oidp);
+ }
+ break;
+ }
case SILC_ID_SERVER:
SILC_LOG_DEBUG(("Old Server ID id(%s)",
("Your host is %s, running version %s",
server->config->server_info->server_name,
server_version));
+ if (server->server_type == SILC_ROUTER) {
+ SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+ ("There are %d clients on %d servers in SILC "
+ "Network", server->stat.clients,
+ server->stat.servers + 1));
+ SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+ ("There are %d clients on %d server in our cell",
+ server->stat.cell_clients,
+ server->stat.cell_servers));
+ SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+ ("I have %d clients, %d channels, %d servers and "
+ "%d routers",
+ server->stat.my_clients,
+ server->stat.my_channels,
+ server->stat.my_servers,
+ server->stat.my_routers));
+ SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+ ("%d server operators and %d router operators "
+ "online",
+ server->stat.my_server_ops,
+ server->stat.my_router_ops));
+ } else {
+ SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+ ("I have %d clients and %d channels formed",
+ server->stat.my_clients,
+ server->stat.my_channels));
+ SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+ ("%d operators online",
+ server->stat.my_server_ops));
+ }
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("Your connection is secured with %s cipher, "
"key length %d bits",
TRUE, new_server->id, SILC_ID_SERVER,
SILC_ID_SERVER_LEN);
+ if (server->server_type == SILC_ROUTER)
+ server->stat.cell_servers++;
+
return new_server;
}
{
SilcBuffer buffer = packet->buffer;
SilcIDList id_list;
- SilcServerEntry tmpserver, router;
+ SilcServerEntry router;
SilcSocketConnection router_sock;
SilcIDPayload idp;
SilcIdType id_type;
unsigned char *hash = NULL;
- void *id, *tmpid;
+ void *id;
SILC_LOG_DEBUG(("Processing new ID"));
buffer->data, buffer->len, FALSE);
}
-#if 0
- /* If the packet is originated from the one who sent it to us we know
- that the ID belongs to our cell, unless the sender was router. */
- tmpid = silc_id_str2id(packet->src_id, SILC_ID_SERVER);
- tmpserver = (SilcServerEntry)sock->user_data;
-
- if (!SILC_ID_SERVER_COMPARE(tmpid, tmpserver->id) &&
- sock->type == SILC_SOCKET_TYPE_SERVER) {
- id_list = server->local_list;
- router_sock = sock;
- router = sock->user_data;
- /* router = server->id_entry; */
- } else {
- id_list = server->global_list;
- router_sock = (SilcSocketConnection)server->router->connection;
- router = server->router;
- }
-
- silc_free(tmpid);
-#endif
-
if (sock->type == SILC_SOCKET_TYPE_SERVER)
id_list = server->local_list;
else
router, router_sock);
entry->nickname = NULL;
+ if (sock->type == SILC_SOCKET_TYPE_SERVER)
+ server->stat.cell_clients++;
+ server->stat.clients++;
+
#if 0
/* XXX Adding two ID's with same IP number replaces the old entry thus
gives wrong route. Thus, now disabled until figured out a better way
list. Cell wide information however is kept in the local list. */
silc_idlist_add_server(id_list, NULL, 0, id, router, router_sock);
+ if (sock->type == SILC_SOCKET_TYPE_SERVER)
+ server->stat.cell_servers++;
+ server->stat.servers++;
+
#if 0
/* Add route cache for this ID */
silc_server_route_add(silc_server_route_hash(
router hence global channel. */
silc_idlist_add_channel(server->global_list, channel_name, 0, channel_id,
server->router->connection, NULL);
+
+ server->stat.channels++;
}
/* Received notify packet. Server can receive notify packets from router.
SilcNotifyType type;
SilcArgumentPayload args;
SilcChannelID *channel_id;
- SilcClientID *client_id;
+ SilcClientID *client_id, *client_id2;
SilcChannelEntry channel;
SilcClientEntry client;
unsigned char *tmp;
}
client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ /* Send to channel */
+ silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
+ FALSE, packet->buffer->data,
+ packet->buffer->len, FALSE);
+
/* If the the client is not in local list we check global list (ie. the
channel will be global channel) and if it does not exist then create
entry for the client. */
} else {
silc_free(client_id);
}
-
- /* Send to channel */
- silc_server_packet_send_to_channel(server, channel, packet->type, FALSE,
- packet->buffer->data,
- packet->buffer->len, FALSE);
break;
case SILC_NOTIFY_TYPE_LEAVE:
client_id = silc_id_payload_parse_id(tmp, tmp_len);
/* Send to channel */
- silc_server_packet_send_to_channel(server, channel, packet->type, FALSE,
- packet->buffer->data,
+ silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
+ FALSE, packet->buffer->data,
packet->buffer->len, FALSE);
/* Get client entry */
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
client_id, NULL);
- if (!client)
+ if (!client) {
+ silc_free(client_id);
goto out;
+ }
}
silc_free(client_id);
silc_idlist_del_client(server->global_list, client);
break;
- /* Ignore rest notify types for now */
- case SILC_NOTIFY_TYPE_NONE:
- case SILC_NOTIFY_TYPE_INVITE:
+ case SILC_NOTIFY_TYPE_NICK_CHANGE:
+ {
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ unsigned char *id, *id2;
+
+ SILC_LOG_DEBUG(("NICK CHANGE notify"));
+
+ /* Get old client ID */
+ id = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!id)
+ goto out;
+ client_id = silc_id_payload_parse_id(id, tmp_len);
+
+ /* Get new client ID */
+ id2 = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (!id2)
+ goto out;
+ client_id2 = silc_id_payload_parse_id(id2, tmp_len);
+
+ SILC_LOG_DEBUG(("Old Client ID id(%s)",
+ silc_id_render(client_id, SILC_ID_CLIENT)));
+ SILC_LOG_DEBUG(("New Client ID id(%s)",
+ silc_id_render(client_id2, SILC_ID_CLIENT)));
+
+ /* Replace the Client ID */
+ client = silc_idlist_replace_client_id(server->global_list, client_id,
+ client_id2);
+ if (!client)
+ client = silc_idlist_replace_client_id(server->local_list, client_id,
+ client_id2);
+
+ if (client)
+ /* Send the NICK_CHANGE notify type to local clients on the channels
+ this client is joined to. */
+ silc_server_send_notify_on_channels(server, client,
+ SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
+ id, tmp_len,
+ id2, tmp_len);
+
+ silc_free(client_id);
+ if (!client)
+ silc_free(client_id2);
+ break;
+ }
case SILC_NOTIFY_TYPE_TOPIC_SET:
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ SILC_LOG_DEBUG(("TOPIC SET notify (not-impl XXX)"));
+ break;
+
case SILC_NOTIFY_TYPE_CMODE_CHANGE:
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ SILC_LOG_DEBUG(("CMODE CHANGE notify (not-impl XXX)"));
+ break;
+
case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ SILC_LOG_DEBUG(("CUMODE CHANGE notify (not-impl XXX)"));
+ break;
+
+ /* Ignore rest notify types for now */
+ case SILC_NOTIFY_TYPE_NONE:
+ case SILC_NOTIFY_TYPE_INVITE:
case SILC_NOTIFY_TYPE_MOTD:
default:
break;
SilcClientEntry client;
SilcChannelEntry channel;
SilcChannelClientEntry chl;
- SilcIDList id_list;
- SilcServerEntry tmpserver, router;
- SilcSocketConnection router_sock;
SilcBuffer clidp;
- void *tmpid;
SILC_LOG_DEBUG(("Start"));
if (!client_id)
goto out;
-#if 0
- /* If the packet is originated from the one who sent it to us we know
- that the ID belongs to our cell, unless the sender was router. */
- tmpid = silc_id_str2id(packet->src_id, SILC_ID_SERVER);
- tmpserver = (SilcServerEntry)sock->user_data;
-
- if (!SILC_ID_SERVER_COMPARE(tmpid, tmpserver->id) &&
- sock->type == SILC_SOCKET_TYPE_SERVER) {
- id_list = server->local_list;
- router_sock = sock;
- router = sock->user_data;
- } else {
- id_list = server->global_list;
- router_sock = (SilcSocketConnection)server->router->connection;
- router = server->router;
- }
- silc_free(tmpid);
-#endif
-
- router_sock = sock;
- router = sock->user_data;
-
/* Find the channel */
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
packet->buffer->data, packet->buffer->len, FALSE);
}
- SILC_LOG_DEBUG(("Client ID: %s", silc_id_render(client_id, SILC_ID_CLIENT)));
-
/* Get client entry */
client = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
if (!client) {
silc_list_add(channel->user_list, chl);
silc_list_add(client->channels, chl);
+ server->stat.chanclients++;
+
/* Send JOIN notify to local clients on the channel. As we are router
it is assured that this is sent only to our local clients and locally
connected servers if needed. */
clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
- silc_server_send_notify_to_channel(server, channel, FALSE,
+ silc_server_send_notify_to_channel(server, sock, channel, FALSE,
SILC_NOTIFY_TYPE_JOIN,
1, clidp->data, clidp->len);
silc_buffer_free(clidp);
/* Remove the client entry */
silc_idlist_del_client(id_list, (SilcClientEntry)id_entry);
+ server->stat.clients--;
SILC_LOG_DEBUG(("Removed client id(%s) from [%s] %s",
silc_id_render(id, SILC_ID_CLIENT),
NULL);
if (id_entry) {
silc_idlist_del_server(id_list, (SilcServerEntry)id_entry);
+ server->stat.servers--;
SILC_LOG_DEBUG(("Removed server id(%s) from [%s] %s",
silc_id_render(id, SILC_ID_SERVER),
NULL);
if (id_entry) {
silc_idlist_del_channel(id_list, (SilcChannelEntry)id_entry);
+ server->stat.channels--;
SILC_LOG_DEBUG(("Removed channel id(%s) from [%s] %s",
silc_id_render(id, SILC_ID_CHANNEL),
out:
silc_id_payload_free(idp);
}
+
+/* Processes received SET_MODE packet. The packet is used to distribute
+ the information about changed channel's or client's channel modes. */
+
+void silc_server_set_mode(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcSetModePayload payload = NULL;
+ SilcArgumentPayload args = NULL;
+ unsigned short mode_type;
+ unsigned int mode_mask;
+ unsigned char *tmp, *tmp2;
+ unsigned int tmp_len, tmp_len2;
+ unsigned char mode[4];
+ SilcClientID *client_id;
+ SilcChannelID *channel_id = NULL;
+ SilcClientEntry client;
+ SilcChannelEntry channel;
+ SilcChannelClientEntry chl;
+
+ if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ packet->src_id_type == SILC_ID_CLIENT)
+ return;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ /* If we are router and this packet is not already broadcast packet
+ we will broadcast it. The sending socket really cannot be router or
+ the router is buggy. If this packet is coming from router then it must
+ have the broadcast flag set already and we won't do anything. */
+ if (!server->standalone && server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+ SILC_LOG_DEBUG(("Broadcasting received Set Mode packet"));
+ silc_server_packet_send(server, server->router->connection, packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ packet->buffer->data, packet->buffer->len, FALSE);
+ }
+
+ /* Parse Set Mode payload */
+ payload = silc_set_mode_payload_parse(packet->buffer);
+ if (!payload)
+ return;
+
+ mode_type = silc_set_mode_get_type(payload);
+ args = silc_set_mode_get_args(payload);
+ if (!args)
+ goto out;
+
+ mode_mask = silc_set_mode_get_mode(payload);
+ SILC_PUT32_MSB(mode_mask, mode);
+
+ switch (mode_type) {
+ case SILC_MODE_TYPE_CHANNEL:
+ /* Get Channel ID */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!tmp)
+ goto out;
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!channel_id)
+ goto out;
+
+ /* Get channel entry */
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel) {
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel)
+ goto out;
+ }
+
+ /* Get Client ID payload */
+ tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (!tmp)
+ goto out;
+
+ /* Send CMODE_CHANGE notify to local channel */
+ silc_server_send_notify_to_channel(server, sock, channel, FALSE,
+ SILC_NOTIFY_TYPE_CMODE_CHANGE,
+ 2, tmp, tmp_len,
+ mode, sizeof(mode));
+
+ /* Change the mode */
+ channel->mode = mode_mask;
+ break;
+
+ case SILC_MODE_TYPE_UCHANNEL:
+ /* Get Channel ID */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!tmp)
+ goto out;
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!channel_id)
+ goto out;
+
+ /* Get channel entry */
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel) {
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel)
+ goto out;
+ }
+
+ /* Get Client ID payload */
+ tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (!tmp)
+ goto out;
+
+ /* Get target Client ID */
+ tmp2 = silc_argument_get_arg_type(args, 3, &tmp_len2);
+ if (!tmp2)
+ goto out;
+ client_id = silc_id_payload_parse_id(tmp2, tmp_len2);
+ if (!client_id)
+ goto out;
+
+ /* Get target client entry */
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, NULL);
+ if (!client) {
+ silc_free(client_id);
+ goto out;
+ }
+ }
+ silc_free(client_id);
+
+ /* Send CUMODE_CHANGE notify to local channel */
+ silc_server_send_notify_to_channel(server, sock, channel, FALSE,
+ SILC_NOTIFY_TYPE_CUMODE_CHANGE, 2,
+ tmp, tmp_len,
+ mode, sizeof(mode),
+ tmp2, tmp_len2);
+
+ /* Get entry to the channel user list */
+ silc_list_start(channel->user_list);
+ while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
+ if (chl->client == client) {
+ /* Change the mode */
+ chl->mode = mode_mask;
+ break;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ out:
+ if (channel_id)
+ silc_free(channel_id);
+ if (args)
+ silc_argument_payload_free(args);
+ if (payload)
+ silc_set_mode_payload_free(payload);
+}