+Sun Mar 18 21:02:47 EET 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Added SILC_NOTIFY_TYPE_KILLED notify type. It is sent when
+ an client is killed from the SILC Network. Updated the protocol
+ specs accordingly.
+
+ Added new function silc_server_send_notify_killed to the
+ silcd/packet_send.[ch].
+
+ * Added function silc_server_packet_relay_notify to relay notify
+ packets that are destined directly to a client. In this case
+ the server does not process the notify packets but merely relays
+ it to the client. Affected file silcd/packet_send.[ch].
+
+ Added also silc_server_packet_process_relay_notify to check
+ whereto relay the notify. Affected file is
+ silcd/packet_receive.[ch].
+
+ * Implemented KILL command to the server.
+
+ * Updated TODO.
+
+ * Added the backup schema desgined last fall to the protocol
+ specs for everyone to see. The specification is in the
+ *-spec-xx.txt draft and the packet type definitions for the
+ backup routers is in *-pp-xx.txt draft. Thusly, added also
+ new packet type SILC_PACKET_CELL_ROUTERS.
+
+ * A big security problem in the implementation discovered. The
+ signoff of an client did not cause new channel key generation
+ which it of course should've done. The channel keys must be
+ always re-generated when client leaves (or signoffs) the channel.
+ The silc_server_remove_from_channels funtion now handles
+ the channel key re-generation.
+
+ * Added `sender' argument to the silc_server_send_notify_on_channels
+ to not to send the client provided as argument. Affected file
+ silcd/packet_send.[ch].
+
Fri Mar 16 15:52:49 EET 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Implemented OPER and SILCOPER commands into the server and
Obtains router operator privileges.
+ /KILL <nickname> [<comment>]
+
+ Router operator can use this command to remove an client
+ from the SILC Network temporarily.
+
/CONNECT <server> [<port>]
Connects to server the remote <server>. You must be
TODO In SILC Server
===================
- o Packet processing can be made faster. All packet function in the
- packet_receive.c has same prototypes. Instead of calling those from
- huge switch() make a table of callback functions that can be called
- directly by the packet type.
+ o Functions such as silc_server_private_message,
+ silc_server_private_message_key and
+ silc_server_packet_process_relay_notify can be optimized. I don't think
+ we need such a big lookups to lookup the router to the destination,
+ it is already provided in the client entry.
o silc_server_send_key_agreement and silc_server_send_private_message_key
are one and same function (also silc_server_send_private_message is
almost same function). These should be unified to one generic named
- function and use that.
+ function and use that (silc_server_packet_relay_notify is also
+ same function).
+
+ o Packet processing can be made faster. All packet function in the
+ packet_receive.c has same prototypes. Instead of calling those from
+ huge switch() make a table of callback functions that can be called
+ directly by the packet type.
o DNS/IP lookup blocks the server. This must be fixed. Check the
resolver stuff (resolver(3), resolver(5)). Either we have to do the
SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
- SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
+ SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
SILC_SERVER_CMD(restart, RESTART,
nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
/* Send NICK_CHANGE notify to the client's channels */
- silc_server_send_notify_on_channels(server, client,
+ silc_server_send_notify_on_channels(server, NULL, client,
SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
oidp->data, oidp->len,
nidp->data, nidp->len);
silc_server_command_free(cmd);
}
+/* Server side of command KILL. This command is used by router operator
+ to remove an client from the SILC Network temporarily. */
+
SILC_SERVER_CMD_FUNC(kill)
{
+ SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+ SilcServer server = cmd->server;
+ SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcClientEntry remote_client;
+ SilcClientID *client_id;
+ unsigned char *tmp, *comment;
+ unsigned int tmp_len;
+ SilcBuffer idp;
+
+ SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
+
+ if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+ goto out;
+
+ if (server->server_type != SILC_ROUTER)
+ goto out;
+
+ /* Check whether client has the permissions. */
+ if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_ERR_NO_ROUTER_PRIV);
+ goto out;
+ }
+
+ /* Get the client ID */
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+ if (!tmp) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
+ client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!client_id) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+ goto out;
+ }
+
+ /* Get the client entry */
+ remote_client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, NULL);
+ if (!remote_client) {
+ remote_client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
+ if (!remote_client) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+ goto out;
+ }
+ }
+
+ /* Get comment */
+ comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+
+ /* Send reply to the sender */
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+ SILC_STATUS_OK);
+
+ /* Send KILLED notify to the channels. It is not sent to the client
+ as it will be sent differently destined directly to the client and not
+ to the channel. */
+ idp = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
+ silc_server_send_notify_on_channels(server, remote_client->connection,
+ remote_client, SILC_NOTIFY_TYPE_KILLED,
+ comment ? 2 : 1,
+ idp->data, idp->len,
+ comment, comment ? strlen(comment) : 0);
+ silc_buffer_free(idp);
+
+ /* Remove the client from all channels. This generates new keys to the
+ channels as well. */
+ silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
+ NULL, TRUE);
+
+ /* Send KILLED notify to the client directly */
+ silc_server_send_notify_killed(server, remote_client->connection ?
+ remote_client->connection :
+ remote_client->router->connection, FALSE,
+ remote_client->id, SILC_ID_CLIENT_LEN,
+ comment);
+
+ /* Send KILLED notify to primary route */
+ if (!server->standalone)
+ silc_server_send_notify_killed(server, server->router->connection,
+ server->server_type == SILC_ROUTER ?
+ TRUE : FALSE,
+ remote_client->id, SILC_ID_CLIENT_LEN,
+ comment);
+
+ out:
+ silc_server_command_free(cmd);
}
/* Server side of command INFO. This sends information about us to
extern char *server_version;
+/* Check whereto relay the received notify packet that was destined
+ to a client. */
+
+static void
+silc_server_packet_process_relay_notify(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcClientID *id;
+ SilcServerEntry router;
+ SilcSocketConnection dst_sock;
+ SilcClientEntry client;
+ SilcIDListData idata;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ /* Decode destination Client ID */
+ id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
+ if (!id) {
+ SILC_LOG_ERROR(("Could not decode destination Client ID, dropped"));
+ return;
+ }
+
+ /* If the destination belongs to our server we don't have to route
+ the packet anywhere but to send it to the local destination. */
+ client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
+ if (client) {
+ /* It exists, now deliver the packet to the destination */
+ dst_sock = (SilcSocketConnection)client->connection;
+
+ /* If we are router and the client has router then the client is in
+ our cell but not directly connected to us. */
+ if (server->server_type == SILC_ROUTER && client->router) {
+ /* We are of course in this case the client's router thus the real
+ "router" of the client is the server who owns the client. Thus
+ we will send the packet to that server. */
+ router = (SilcServerEntry)client->router;
+ idata = (SilcIDListData)router;
+ silc_server_packet_relay_notify(server, router->connection,
+ idata->send_key,
+ idata->hmac,
+ packet);
+ silc_free(id);
+ return;
+ }
+
+ /* Seems that client really is directly connected to us */
+ idata = (SilcIDListData)client;
+ silc_server_packet_relay_notify(server, dst_sock,
+ idata->send_key,
+ idata->hmac, packet);
+ silc_free(id);
+ return;
+ }
+
+ /* Destination belongs to someone not in this server. If we are normal
+ server our action is to send the packet to our router. */
+ if (server->server_type == SILC_SERVER && !server->standalone) {
+ router = server->router;
+
+ /* Send to primary route */
+ if (router) {
+ dst_sock = (SilcSocketConnection)router->connection;
+ idata = (SilcIDListData)router;
+ silc_server_packet_relay_notify(server, dst_sock,
+ idata->send_key,
+ idata->hmac, packet);
+ }
+ silc_free(id);
+ return;
+ }
+
+ /* We are router and we will perform route lookup for the destination
+ and send the packet to fastest route. */
+ if (server->server_type == SILC_ROUTER && !server->standalone) {
+ /* Check first that the ID is valid */
+ client = silc_idlist_find_client_by_id(server->global_list, id, NULL);
+ if (client) {
+ dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
+ router = (SilcServerEntry)dst_sock->user_data;
+ idata = (SilcIDListData)router;
+
+ /* Get fastest route and send packet. */
+ if (router)
+ silc_server_packet_relay_notify(server, dst_sock,
+ idata->send_key,
+ idata->hmac, packet);
+ silc_free(id);
+ return;
+ }
+ }
+}
+
/* Received notify packet. Server can receive notify packets from router.
Server then relays the notify messages to clients if needed. */
packet->src_id_type != SILC_ID_SERVER)
return;
+ /* If the packet is destined directly to a client, then we don't
+ process the packet at all but just relay it to the client. */
+ if (packet->dst_id_type == SILC_ID_CLIENT) {
+ silc_server_packet_process_relay_notify(server, sock, packet);
+ return;
+ }
+
/* 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
tmp = NULL;
/* Remove the client from all channels */
- silc_server_remove_from_channels(server, NULL, client, tmp);
+ silc_server_remove_from_channels(server, NULL, client, TRUE, tmp, TRUE);
/* Remove the client entry */
if (!silc_idlist_del_client(server->global_list, 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_server_send_notify_on_channels(server, NULL, client,
SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
id, tmp_len,
id2, tmp_len);
break;
+ case SILC_NOTIFY_TYPE_KILLED:
+ /*
+ * Distribute the notify to local clients on channels
+ */
+
+ SILC_LOG_DEBUG(("KILLED notify"));
+
+ break;
+
/* Ignore rest of the notify types for now */
case SILC_NOTIFY_TYPE_NONE:
case SILC_NOTIFY_TYPE_MOTD:
idata->send_key,
idata->hmac,
packet);
+ silc_free(id);
return;
}
silc_server_send_private_message(server, dst_sock,
idata->send_key,
idata->hmac, packet);
+ silc_free(id);
return;
}
idata->send_key,
idata->hmac, packet);
}
+ silc_free(id);
return;
}
silc_server_send_private_message(server, dst_sock,
idata->send_key,
idata->hmac, packet);
+ silc_free(id);
return;
}
}
idata->send_key,
idata->hmac,
packet);
+ silc_free(id);
return;
}
silc_server_send_private_message_key(server, dst_sock,
idata->send_key,
idata->hmac, packet);
+ silc_free(id);
return;
}
idata->send_key,
idata->hmac, packet);
}
+ silc_free(id);
return;
}
silc_server_send_private_message_key(server, dst_sock,
idata->send_key,
idata->hmac, packet);
+ silc_free(id);
return;
}
}
}
/* If the destination belongs to our server we don't have to route
- the message anywhere but to send it to the local destination. */
+ the packet anywhere but to send it to the local destination. */
client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
if (client) {
- /* It exists, now deliver the message to the destination */
+ /* It exists, now deliver the packet to the destination */
dst_sock = (SilcSocketConnection)client->connection;
/* If we are router and the client has router then the client is in
idata->send_key,
idata->hmac,
packet);
+ silc_free(id);
return;
}
silc_server_send_key_agreement(server, dst_sock,
idata->send_key,
idata->hmac, packet);
+ silc_free(id);
return;
}
idata->send_key,
idata->hmac, packet);
}
+ silc_free(id);
return;
}
silc_server_send_key_agreement(server, dst_sock,
idata->send_key,
idata->hmac, packet);
+ silc_free(id);
return;
}
}
silc_buffer_free(idp);
}
+/* Send KILLED notify type. This tells that the `client_id' client was
+ killed from the network. The `comment' may indicate the reason
+ for the killing. */
+
+void silc_server_send_notify_killed(SilcServer server,
+ SilcSocketConnection sock,
+ int broadcast,
+ SilcClientID *client_id,
+ unsigned int client_id_len,
+ char *comment)
+{
+ SilcBuffer idp;
+
+ idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+ silc_server_send_notify_dest(server, sock, broadcast, (void *)client_id,
+ SILC_ID_CLIENT, SILC_NOTIFY_TYPE_KILLED,
+ comment ? 2 : 1, idp->data, idp->len,
+ comment, comment ? strlen(comment) : 0);
+ silc_buffer_free(idp);
+}
+
/* Sends notify message destined to specific entity. */
void silc_server_send_notify_dest(SilcServer server,
local servers if we are router). */
void silc_server_send_notify_on_channels(SilcServer server,
+ SilcSocketConnection sender,
SilcClientEntry client,
SilcNotifyType type,
unsigned int argc, ...)
sock = (SilcSocketConnection)c->router->connection;
idata = (SilcIDListData)c->router;
+ if (sender && sock == sender)
+ continue;
+
packetdata.dst_id = silc_id_id2str(c->router->id, SILC_ID_SERVER);
packetdata.dst_id_len = SILC_ID_SERVER_LEN;
packetdata.dst_id_type = SILC_ID_SERVER;
sock = (SilcSocketConnection)c->connection;
idata = (SilcIDListData)c;
+ if (sender && sock == sender)
+ continue;
+
packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT);
packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
packetdata.dst_id_type = SILC_ID_CLIENT;
/* Send the packet */
silc_server_packet_send_real(server, dst_sock, FALSE);
}
+
+/* Routine used to relay notify packets to a client. The notify packets
+ may be destined directly to a client and this routine is used to do
+ that. */
+
+void silc_server_packet_relay_notify(SilcServer server,
+ SilcSocketConnection dst_sock,
+ SilcCipher cipher,
+ SilcHmac hmac,
+ SilcPacketContext *packet)
+{
+ silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
+ + packet->dst_id_len + packet->padlen);
+ silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len);
+ silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len);
+
+ /* Re-encrypt packet */
+ silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, packet->buffer->len);
+
+ /* Send the packet */
+ silc_server_packet_send_real(server, dst_sock, FALSE);
+}
SilcClientID *client_id,
unsigned int client_id_len,
char *comment);
+void silc_server_send_notify_killed(SilcServer server,
+ SilcSocketConnection sock,
+ int broadcast,
+ SilcClientID *client_id,
+ unsigned int client_id_len,
+ char *comment);
void silc_server_send_notify_dest(SilcServer server,
SilcSocketConnection sock,
int broadcast,
SilcNotifyType type,
unsigned int argc, ...);
void silc_server_send_notify_on_channels(SilcServer server,
+ SilcSocketConnection sender,
SilcClientEntry client,
SilcNotifyType type,
unsigned int argc, ...);
SilcCipher cipher,
SilcHmac hmac,
SilcPacketContext *packet);
+void silc_server_packet_relay_notify(SilcServer server,
+ SilcSocketConnection dst_sock,
+ SilcCipher cipher,
+ SilcHmac hmac,
+ SilcPacketContext *packet);
#endif
{
FreeClientInternal i = silc_calloc(1, sizeof(*i));
- /* Send REMOVE_ID packet to routers. */
+ /* Send SIGNOFF notify to routers. */
if (!server->standalone && server->router)
silc_server_send_notify_signoff(server, server->router->connection,
server->server_type == SILC_SERVER ?
SILC_ID_CLIENT_LEN, signoff);
/* Remove client from all channels */
- silc_server_remove_from_channels(server, sock, client, signoff);
+ silc_server_remove_from_channels(server, sock, client, TRUE, signoff, TRUE);
/* We will not delete the client entry right away. We will take it
into history (for WHOWAS command) for 5 minutes */
}
/* Remove the client entry */
- silc_server_remove_from_channels(server, NULL, client, NULL);
+ silc_server_remove_from_channels(server, NULL, client, TRUE,
+ NULL, TRUE);
silc_idlist_del_client(server->local_list, client);
if (!silc_idcache_list_next(list, &id_cache))
}
/* Remove the client entry */
- silc_server_remove_from_channels(server, NULL, client, NULL);
+ silc_server_remove_from_channels(server, NULL, client, TRUE,
+ NULL, TRUE);
silc_idlist_del_client(server->global_list, client);
if (!silc_idcache_list_next(list, &id_cache))
void silc_server_remove_from_channels(SilcServer server,
SilcSocketConnection sock,
SilcClientEntry client,
- char *signoff_message)
+ int notify,
+ char *signoff_message,
+ int keygen)
{
SilcChannelEntry channel;
SilcChannelClientEntry chl;
if (server->server_type == SILC_SERVER &&
!silc_server_channel_has_local(channel)) {
/* Notify about leaving client if this channel has global users. */
- if (channel->global_users)
+ if (notify && channel->global_users)
silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
SILC_NOTIFY_TYPE_SIGNOFF,
signoff_message ? 2 : 1,
/* Send notify to channel about client leaving SILC and thus
the entire channel. */
- silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
- SILC_NOTIFY_TYPE_SIGNOFF,
- signoff_message ? 2 : 1,
- clidp->data, clidp->len,
- signoff_message, signoff_message ?
- strlen(signoff_message) : 0);
+ if (notify)
+ silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
+ SILC_NOTIFY_TYPE_SIGNOFF,
+ signoff_message ? 2 : 1,
+ clidp->data, clidp->len,
+ signoff_message, signoff_message ?
+ strlen(signoff_message) : 0);
+
+ if (keygen) {
+ /* Re-generate channel key */
+ silc_server_create_channel_key(server, channel, 0);
+
+ /* Send the channel key to the channel. The key of course is not sent
+ to the client who was removed f rom the channel. */
+ silc_server_send_channel_key(server, client->connection, channel,
+ server->server_type == SILC_ROUTER ?
+ FALSE : !server->standalone);
+ }
}
silc_buffer_free(clidp);
unsigned char channel_key[32], hash[32];
unsigned int len;
+ SILC_LOG_DEBUG(("Generating channel key"));
+
if (!channel->channel_key)
if (!silc_cipher_alloc("aes-256-cbc", &channel->channel_key))
return;
void silc_server_remove_from_channels(SilcServer server,
SilcSocketConnection sock,
SilcClientEntry client,
- char *signoff_message);
+ int notify,
+ char *signoff_message,
+ int keygen);
int silc_server_remove_from_one_channel(SilcServer server,
SilcSocketConnection sock,
SilcChannelEntry channel,
aes-192-cbc:../lib/silcsim/modules/aes.sim.so:24:16
aes-128-cbc:../lib/silcsim/modules/aes.sim.so:16:16
twofish-256-cbc:../lib/silcsim/modules/twofish.sim.so:32:16
-twofish-192-cbc:../lib/silcsim/modules/twofish.sim.so:24:16
+twofish-192-cbc:../lib/silcsim/modules/twofish.sim.so:24:16
twofish-128-cbc:../lib/silcsim/modules/twofish.sim.so:16:16
mars-256-cbc:../lib/silcsim/modules/mars.sim.so:32:16
mars-192-cbc:../lib/silcsim/modules/mars.sim.so:24:16
[hmac]
hmac-sha1-96:sha1:12
hmac-md5-96:md5:12
-hmac-sha1:sha1:20
+hmac-sha1:sha1:20
hmac-md5:md5:16
#[PKCS]
Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
[ServerInfo]
-lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:212.146.42.253:Kuopio, Finland:1334
[ListenPort]
-10.2.1.7:10.2.1.7:1334
+212.146.42.253:212.146.42.253:1334
[Logging]
infologfile:silcd2.log:10000
[AdminConnection]
[ServerConnection]
-10.2.1.7:passwd:priikone:1333:1:1
+212.146.42.253:passwd:priikone:1336:1:1
[RouterConnection]
-10.2.1.7:passwd:priikone:1335:1:1:0
+212.146.42.253:passwd:priikone:1335:1:1:0
[DenyConnection]
[RedirectClient]
Payload of the packet: See section 2.3.20 Key Agreement Payload
- 26 - 199
+ 26 SILC_PACKET_CELL_ROUTERS
+
+ This packet is used by primary router in the cell to notify its
+ primary router what other routers (backup routers) exist in the
+ cell. In case of failure of the primary router in the cell the
+ first router in the list will act as primary router of the cell.
+ This packet may be sent at anytime after connection has been
+ registered to the primary router. The client must not send this
+ packet.
+
+ Payload of the packet: See section 2.3.21 Cell Routers Payload
+
+
+ 27 - 199
Currently undefined commands.
The kicker may have set the <comment> to indicate the reason for
the kicking.
+
+13 SILC_NOTIFY_TYPE_KILLED
+
+ Sent when a client has been killed from the network. This is sent
+ also to the client who was killed from the network. The client
+ who was killed from the network must be removed from the network.
+ This notify type is destined directly to the client who was killed
+ and to channel if the client is on any channel. The router or
+ server receiving the packet distributes this type to the local
+ clients on the channel and broadcast it to the network.
+
+ Max Arguments: 2
+ Arguments: (1) <Client ID> (2) [<comment>]
+
+ The <Client ID> is the client who was killed from the network.
+ The killer may have set the <comment> to indicate the reason for
+ the killing.
+
.in 3
Notify types starting from 16384 are reserved for private notify
client ID.
The payload may only be sent with SILC_PACKET_NEW_CLIENT packet. It
-must not be sent in any other packet type. The following diagram represents
-the New Client Payload.
+must not be sent in any other packet type. The following diagram
+represents the New Client Payload.
Figure 20: Key Agreement Payload
-
.in 6
o Hostname Length (2 bytes) - Indicates the length of the Hostname
field.
the key material is undefined.
+.ti 0
+2.3.21 Cell Routers Payload
+
+Cell Routers payload is used by router to notify its primary router what
+other routers exist in the cell. The other routers are considered to be
+backup routers and one of them will come active only in the case of
+failure of the primary router. Normal server can send this packet if it
+is acting as backup router. Client must not send this packet. To send
+more than one backup router set the List flag and assemble the payloads
+as list.
+
+The payload may only be sent with SILC_PACKET_CELL_ROUTERS packet. It
+must not be sent in any other packet type. The Following diagram
+represents the Cell Routers Payload.
+
+
+.in 5
+.nf
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Hostname Length | |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+| |
+~ Hostname ~
+| |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Port |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Server ID Length | |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+| |
+~ Server ID ~
+| |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 21: Cell Routers Payload
+
+
+.in 6
+o Hostname Length (2 bytes) - Indicates the length of the Hostname
+ field.
+
+o Hostname (variable length) - The hostname or IP address of
+ the backup router.
+
+o Port (4 bytes) - The port of the backup router it currently uses.
+ This is a 32 bit MSB first order value.
+
+o Server ID Length (2 bytes) - Indicates the length of the Server
+ ID field.
+
+o Server ID (variable length) - Consists of the Server ID of the
+ backup router.
+.in 3
+
+
.ti 0
2.4 SILC ID Types
2.3 Communication in the Network .............................. 6
2.4 Channel Communication ..................................... 7
2.5 Router Connections ........................................ 7
+ 2.6 Backup Routers ............................................ XX
3 SILC Specification ............................................ 8
3.1 Client .................................................... 8
3.1.1 Client ID ........................................... 9
distributed by SILC broadcast packets.
+.ti 0
+2.6 Backup Routers
+
+Backup routers may exist in the cell in addition of the primary router.
+However, they must not be active routers and act as routers in the cell.
+Only one router may be acting as primary router in the cell. In the case
+of failure of the primary router may one of the backup routers become
+active. The purpose of backup routers are in case of failure of the
+primary router to maintain working connections inside the cell and outside
+the cell and to avoid netsplits.
+
+Backup routers are normal servers in the cell that are prepared to take
+over the tasks of primary router if needed. They need to have at least
+one direct and active connection to the primary router of the cell.
+This communication channel is used to send the router information to
+the backup router. Backup router must know everything that the primary
+router knows to be able to take over the tasks of the primary router.
+It is the primary router's responsibility to feed the data to the backup
+router. If the backup router does not know all the data in the case of
+failure some connections may be lost. The primary router of the cell
+must consider the backup router being normal router server and feed the
+data accordingly.
+
+In addition of having direct connection to the primary router of the
+cell the backup router must also have connection to the same router
+the primary router of the cell has connected. However, it must not be
+active router connection meaning that the backup router must not use
+that channel as its primary route and it must not notify the router
+about having connected servers, channels and clients behind it. It
+merely connects to the router. This sort of connection is later
+referred as being passive connection. Some keepalive actions may be
+needed by the router to keep the connection alive.
+
+The primary router notifies its primary router about having backup
+routers in the cell by sending SILC_PACKET_CELL_ROUTERS packet. If
+and when the primary router of the cell becomes unresponsive, its
+primary router knows that there exists backup routers in the cell.
+After that it will start using the first backup router sent in the
+packet as router of that cell. In this case the backup router must
+notify its new primary router about the servers, channels and clients
+it has connected to it. The primary router knows that this server
+has become a router of the cell because of failure of the primary
+router in the cell. It must also cope with the fact that the servers,
+channels and clients that the new backup router announces are not
+really new, since they used to exist in the primary router of the
+cell.
+
+It is required that other normal servers has passive connections to
+the backup router(s) in the cell. Some keepalive actions may be needed
+by the server to keep the connection alive. After they notice the
+failure of the primary router they must start using the connection to
+the first backup router as their primary route.
+
+It is recommended that there would be at least one backup router in
+the cell. It is not recommended to have all servers in the cell acting
+as backup routers as it requires establishing several connections to
+several servers in the cell. Large cells can easily have several
+backup routers in the cell. The order of the backup routers are decided
+at the primary router of the cell and servers and backup servers in the
+cell must be configured accordingly. It is not required that the backup
+server is actually active server in the cell. Backup router may be spare
+server in the cell that does not accept normal client connections at all.
+It maybe reserved purely for the backup purposes. These, however, are
+cell management issues.
+
+If the first backup router is down as well and there is another backup
+router in the cell then it will start acting as the primary router as
+described above.
+
+
.ti 0
3. SILC Specification
#define SILC_NOTIFY_TYPE_CHANNEL_CHANGE 10 /* Channel's ID has changed */
#define SILC_NOTIFY_TYPE_SERVER_SIGNOFF 11 /* Server quitting SILC */
#define SILC_NOTIFY_TYPE_KICKED 12 /* Kicked from channel */
+#define SILC_NOTIFY_TYPE_KILLED 13 /* Killed from the network */
/* Prototypes */
SilcNotifyPayload silc_notify_payload_parse(SilcBuffer buffer);
#define SILC_PACKET_REKEY_DONE 23 /* Re-key done */
#define SILC_PACKET_HEARTBEAT 24 /* Heartbeat */
#define SILC_PACKET_KEY_AGREEMENT 25 /* Key Agreement request */
+#define SILC_PACKET_CELL_ROUTERS 26 /* Cell routers backup */
#define SILC_PACKET_PRIVATE 200 /* Private range start */
#define SILC_PACKET_MAX 255 /* RESERVED */