X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fpacket_receive.c;h=65aba7318907e6c024dc0769da3c76a1570b54b2;hb=386c883d8774999c6e74d7c6c37e52e4163a4cb1;hp=983d44f3015253cb313353c4c1ce61d1cb70547f;hpb=9c4f7f18c31afa9dbaf4540c30cafd980b29c318;p=silc.git diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 983d44f3..65aba731 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -49,6 +49,7 @@ void silc_server_notify(SilcServer server, uint32 mode; unsigned char *tmp; uint32 tmp_len; + bool local; SILC_LOG_DEBUG(("Start")); @@ -71,11 +72,13 @@ void silc_server_notify(SilcServer server, if (dst_sock) /* Relay the packet */ silc_server_relay_packet(server, dst_sock, idata->send_key, - idata->hmac_receive, packet, TRUE); + idata->hmac_receive, idata->psn_send++, + packet, TRUE); } /* Parse the Notify Payload */ - payload = silc_notify_payload_parse(packet->buffer); + payload = silc_notify_payload_parse(packet->buffer->data, + packet->buffer->len); if (!payload) return; @@ -178,7 +181,7 @@ void silc_server_notify(SilcServer server, client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL, silc_id_dup(client_id, SILC_ID_CLIENT), - sock->user_data, NULL); + sock->user_data, NULL, 0); if (!client) { SILC_LOG_ERROR(("Could not add new client to the ID Cache")); silc_free(client_id); @@ -209,6 +212,8 @@ void silc_server_notify(SilcServer server, /* The channel is global now */ channel->global_users = TRUE; + SILC_LOG_DEBUG(("Joining to channel %s", channel->channel_name)); + /* JOIN the global client to the channel (local clients (if router created the channel) is joined in the pending JOIN command). */ chl = silc_calloc(1, sizeof(*chl)); @@ -223,6 +228,7 @@ void silc_server_notify(SilcServer server, silc_hash_table_add(channel->user_list, client, chl); silc_hash_table_add(client->channels, channel, chl); silc_free(client_id); + channel->user_count++; break; @@ -322,14 +328,18 @@ void silc_server_notify(SilcServer server, if (tmp_len > 128) tmp = NULL; + /* Update statistics */ + server->stat.clients--; + if (server->server_type == SILC_ROUTER) + server->stat.cell_clients--; + SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR); + SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); + /* Remove the client from all channels. */ silc_server_remove_from_channels(server, NULL, client, TRUE, tmp, FALSE); client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; cache->expire = SILC_ID_CACHE_EXPIRE_DEF; - server->stat.clients--; - if (server->server_type == SILC_ROUTER) - server->stat.cell_clients--; break; case SILC_NOTIFY_TYPE_TOPIC_SET: @@ -365,10 +375,8 @@ void silc_server_notify(SilcServer server, goto out; } - if (channel->topic) - silc_free(channel->topic); - channel->topic = silc_calloc(tmp_len + 1, sizeof(*channel->topic)); - memcpy(channel->topic, tmp, tmp_len); + silc_free(channel->topic); + channel->topic = strdup(tmp); /* Send the same notify to the channel */ silc_server_packet_send_to_channel(server, sock, channel, packet->type, @@ -518,6 +526,13 @@ void silc_server_notify(SilcServer server, memset(hash, 0, sizeof(hash)); } + /* Get the passphrase */ + tmp = silc_argument_get_arg_type(args, 5, &tmp_len); + if (tmp) { + silc_free(channel->passphrase); + channel->passphrase = strdup(tmp); + } + break; case SILC_NOTIFY_TYPE_CUMODE_CHANGE: @@ -616,6 +631,7 @@ void silc_server_notify(SilcServer server, if (chl2) { chl2->mode = mode; silc_free(channel_id); + silc_hash_table_list_reset(&htl); goto out; } } @@ -626,6 +642,8 @@ void silc_server_notify(SilcServer server, break; } + SILC_LOG_DEBUG(("Changing the channel user mode")); + /* Change the mode */ chl->mode = mode; if (!(mode & SILC_CHANNEL_UMODE_CHANFO)) @@ -634,6 +652,7 @@ void silc_server_notify(SilcServer server, chl2 = chl; } } + silc_hash_table_list_reset(&htl); /* Send the same notify to the channel */ if (!notify_sent) @@ -738,10 +757,10 @@ void silc_server_notify(SilcServer server, goto out; /* Get the channel entry */ - channel = silc_idlist_find_channel_by_id(server->global_list, + channel = silc_idlist_find_channel_by_id(server->local_list, channel_id, NULL); if (!channel) { - channel = silc_idlist_find_channel_by_id(server->local_list, + channel = silc_idlist_find_channel_by_id(server->global_list, channel_id, NULL); if (!channel) { silc_free(channel_id); @@ -768,9 +787,9 @@ void silc_server_notify(SilcServer server, silc_id_render(channel_id2, SILC_ID_CHANNEL))); /* Replace the Channel ID */ - if (!silc_idlist_replace_channel_id(server->global_list, channel_id, + if (!silc_idlist_replace_channel_id(server->local_list, channel_id, channel_id2)) - if (!silc_idlist_replace_channel_id(server->local_list, channel_id, + if (!silc_idlist_replace_channel_id(server->global_list, channel_id, channel_id2)) { silc_free(channel_id2); channel_id2 = NULL; @@ -778,7 +797,14 @@ void silc_server_notify(SilcServer server, if (channel_id2) { SilcBuffer users = NULL, users_modes = NULL; - + + /* Re-announce this channel which ID was changed. */ + silc_server_send_new_channel(server, sock, FALSE, channel->channel_name, + channel->id, + silc_id_get_len(channel->id, + SILC_ID_CHANNEL), + channel->mode); + /* Re-announce our clients on the channel as the ID has changed now */ silc_server_announce_get_channel_users(server, channel, &users, &users_modes); @@ -798,6 +824,15 @@ void silc_server_notify(SilcServer server, users_modes->len, FALSE); silc_buffer_free(users_modes); } + + /* Re-announce channel's topic */ + if (channel->topic) { + silc_server_send_notify_topic_set(server, sock, + server->server_type == SILC_ROUTER ? + TRUE : FALSE, channel, + channel->id, SILC_ID_CHANNEL, + channel->topic); + } } silc_free(channel_id); @@ -822,10 +857,61 @@ void silc_server_notify(SilcServer server, /* Get server entry */ server_entry = silc_idlist_find_server_by_id(server->global_list, server_id, TRUE, NULL); + local = TRUE; if (!server_entry) { server_entry = silc_idlist_find_server_by_id(server->local_list, server_id, TRUE, NULL); + local = TRUE; if (!server_entry) { + /* If we are normal server then we might not have the server. Check + whether router was kind enough to send the list of all clients + that actually was to be removed. Remove them if the list is + available. */ + if (server->server_type != SILC_ROUTER && + silc_argument_get_arg_num(args) > 1) { + int i; + + for (i = 1; i < silc_argument_get_arg_num(args); i++) { + /* Get Client ID */ + tmp = silc_argument_get_arg_type(args, i + 1, &tmp_len); + if (!tmp) + continue; + client_id = silc_id_payload_parse_id(tmp, tmp_len); + if (!client_id) + continue; + + /* Get client entry */ + client = silc_idlist_find_client_by_id(server->global_list, + client_id, TRUE, &cache); + local = TRUE; + if (!client) { + client = silc_idlist_find_client_by_id(server->local_list, + client_id, TRUE, &cache); + local = FALSE; + if (!client) { + silc_free(client_id); + continue; + } + } + silc_free(client_id); + + /* Update statistics */ + server->stat.clients--; + if (server->server_type == SILC_ROUTER) + server->stat.cell_clients--; + SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR); + SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); + + /* Remove the client from all channels. */ + silc_server_remove_from_channels(server, NULL, client, + TRUE, NULL, FALSE); + + /* Remove the client */ + silc_idlist_del_client(local ? server->local_list : + server->global_list, client); + } + } + silc_free(server_id); goto out; } @@ -837,8 +923,8 @@ void silc_server_notify(SilcServer server, silc_server_remove_clients_by_server(server, server_entry, TRUE); /* Remove the server entry */ - if (!silc_idlist_del_server(server->global_list, server_entry)) - silc_idlist_del_server(server->local_list, server_entry); + silc_idlist_del_server(local ? server->local_list : + server->global_list, server_entry); /* XXX update statistics */ @@ -967,7 +1053,7 @@ void silc_server_notify(SilcServer server, */ SILC_LOG_DEBUG(("UMODE_CHANGE notify")); - + /* Get client ID */ tmp = silc_argument_get_arg_type(args, 1, &tmp_len); if (!tmp) @@ -993,9 +1079,33 @@ void silc_server_notify(SilcServer server, tmp = silc_argument_get_arg_type(args, 2, &tmp_len); if (!tmp) goto out; + SILC_GET32_MSB(mode, tmp); + +#define SILC_UMODE_STATS_UPDATE(oper, mod) \ +do { \ + if (client->mode & (mod)) { \ + if (!(mode & (mod))) { \ + if (client->connection) \ + server->stat.my_ ## oper ## _ops--; \ + if (server->server_type == SILC_ROUTER) \ + server->stat. oper ## _ops--; \ + } \ + } else { \ + if (mode & (mod)) { \ + if (client->connection) \ + server->stat.my_ ## oper ## _ops++; \ + if (server->server_type == SILC_ROUTER) \ + server->stat. oper ## _ops++; \ + } \ + } \ +} while(0) + + /* Update statistics */ + SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR); + SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR); /* Save the mode */ - SILC_GET32_MSB(client->mode, tmp); + client->mode = mode; break; @@ -1047,7 +1157,7 @@ void silc_server_notify(SilcServer server, if (tmp && channel->ban_list) { char *start, *end, *n; - if (!strcmp(channel->ban_list, tmp)) { + if (!strncmp(channel->ban_list, tmp, strlen(channel->ban_list) - 1)) { silc_free(channel->ban_list); channel->ban_list = NULL; } else { @@ -1063,7 +1173,6 @@ void silc_server_notify(SilcServer server, } } } - break; /* Ignore rest of the notify types for now */ @@ -1147,21 +1256,45 @@ void silc_server_private_message(SilcServer server, SILC_LOG_DEBUG(("Start")); if (packet->src_id_type != SILC_ID_CLIENT || - packet->dst_id_type != SILC_ID_CLIENT) - return; - - if (!packet->dst_id) + packet->dst_id_type != SILC_ID_CLIENT || !packet->dst_id) return; /* Get the route to the client */ dst_sock = silc_server_get_client_route(server, packet->dst_id, packet->dst_id_len, NULL, &idata); - if (!dst_sock) + if (!dst_sock) { + /* Send IDENTIFY command reply with error status to indicate that + such destination ID does not exist or is invalid */ + SilcBuffer idp = silc_id_payload_encode_data(packet->dst_id, + packet->dst_id_len, + packet->dst_id_type); + if (!idp) + return; + + if (packet->src_id_type == SILC_ID_CLIENT) { + SilcClientID *client_id = silc_id_str2id(packet->src_id, + packet->src_id_len, + packet->src_id_type); + silc_server_send_dest_command_reply(server, sock, + client_id, SILC_ID_CLIENT, + SILC_COMMAND_IDENTIFY, + SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, + 0, 1, 2, idp->data, idp->len); + silc_free(client_id); + } else { + silc_server_send_command_reply(server, sock, SILC_COMMAND_IDENTIFY, + SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, + 0, 1, 2, idp->data, idp->len); + } + + silc_buffer_free(idp); return; + } /* Send the private message */ silc_server_send_private_message(server, dst_sock, idata->send_key, - idata->hmac_send, packet); + idata->hmac_send, idata->psn_send++, + packet); } /* Received private message key packet.. This packet is never for us. It is to @@ -1193,7 +1326,7 @@ void silc_server_private_message_key(SilcServer server, /* Relay the packet */ silc_server_relay_packet(server, dst_sock, idata->send_key, - idata->hmac_send, packet, FALSE); + idata->hmac_send, idata->psn_send++, packet, FALSE); } /* Processes incoming command reply packet. The command reply packet may @@ -1235,7 +1368,7 @@ void silc_server_command_reply(SilcServer server, if (packet->dst_id_type == SILC_ID_SERVER) { /* For now this must be for us */ - if (memcmp(packet->dst_id, server->id_string, packet->dst_id_len)) { + if (memcmp(packet->dst_id, server->id_string, server->id_string_len)) { SILC_LOG_ERROR(("Cannot process command reply to unknown server")); return; } @@ -1257,8 +1390,8 @@ void silc_server_command_reply(SilcServer server, idata = (SilcIDListData)client; /* Encrypt packet */ - silc_packet_encrypt(idata->send_key, idata->hmac_send, dst_sock->outbuf, - buffer->len); + silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++, + dst_sock->outbuf, buffer->len); /* Send the packet */ silc_server_packet_send_real(server, dst_sock, TRUE); @@ -1390,6 +1523,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, SilcBuffer reply; SilcIDListData idata; char *username = NULL, *realname = NULL, *id_string; + uint16 username_len; uint32 id_len; int ret; char *hostname, *nickname; @@ -1404,7 +1538,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, client = (SilcClientEntry)sock->user_data; idata = (SilcIDListData)client; - /* Remove the old cache entry */ + /* Remove the old cache entry. */ if (!silc_idcache_del_by_context(server->local_list->clients, client)) { SILC_LOG_ERROR(("Lost client's cache entry - bad thing")); silc_server_disconnect_remote(server, sock, "Server closed connection: " @@ -1414,14 +1548,13 @@ SilcClientEntry silc_server_new_client(SilcServer server, /* Parse incoming packet */ ret = silc_buffer_unformat(buffer, - SILC_STR_UI16_STRING_ALLOC(&username), + SILC_STR_UI16_NSTRING_ALLOC(&username, + &username_len), SILC_STR_UI16_STRING_ALLOC(&realname), SILC_STR_END); if (ret == -1) { - if (username) - silc_free(username); - if (realname) - silc_free(realname); + silc_free(username); + silc_free(realname); silc_server_disconnect_remote(server, sock, "Server closed connection: " "Incomplete client information"); return NULL; @@ -1429,17 +1562,22 @@ SilcClientEntry silc_server_new_client(SilcServer server, if (!username) { silc_free(username); - if (realname) - silc_free(realname); + silc_free(realname); silc_server_disconnect_remote(server, sock, "Server closed connection: " "Incomplete client information"); return NULL; } - if (strlen(username) > 128) - username[127] = '\0'; + if (username_len > 128) + username[128] = '\0'; - nickname = strdup(username); + /* Check for bad characters for nickname, and modify the nickname if + it includes those. */ + if (silc_server_name_bad_chars(username, username_len)) { + nickname = silc_server_name_modify_bad(username, username_len); + } else { + nickname = strdup(username); + } /* Make sanity checks for the hostname of the client. If the hostname is provided in the `username' check that it is the same than the @@ -1451,15 +1589,13 @@ SilcClientEntry silc_server_new_client(SilcServer server, int tlen = strcspn(username, "@"); char *phostname = NULL; - hostname = silc_calloc((strlen(username) - tlen) + 1, sizeof(char)); - memcpy(hostname, username + tlen + 1, strlen(username) - tlen - 1); + hostname = silc_memdup(username + tlen + 1, strlen(username) - tlen - 1); if (strcmp(sock->hostname, sock->ip) && strcmp(sock->hostname, hostname)) { silc_free(username); silc_free(hostname); - if (realname) - silc_free(realname); + silc_free(realname); silc_server_disconnect_remote(server, sock, "Server closed connection: " "Incomplete client information"); @@ -1476,18 +1612,15 @@ SilcClientEntry silc_server_new_client(SilcServer server, phostname && strcmp(phostname, hostname)) { silc_free(username); silc_free(hostname); - if (phostname) - silc_free(phostname); - if (realname) - silc_free(realname); + silc_free(phostname); + silc_free(realname); silc_server_disconnect_remote(server, sock, "Server closed connection: " "Incomplete client information"); return NULL; } - if (phostname) - silc_free(phostname); + silc_free(phostname); } else { /* The hostname is not present, add it. */ char *newusername; @@ -1542,7 +1675,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, /* Add the client again to the ID cache */ silc_idcache_add(server->local_list->clients, client->nickname, - client_id, client, FALSE); + client_id, client, 0, NULL); /* Notify our router about new client on the SILC network */ if (!server->standalone) @@ -1590,10 +1723,14 @@ SilcClientEntry silc_server_new_client(SilcServer server, 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)); + ("There are %d server operators and %d router " + "operators online", + server->stat.server_ops, + server->stat.router_ops)); + SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, + ("I have %d operators online", + server->stat.my_router_ops + + server->stat.my_server_ops)); } else { SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, ("I have %d clients and %d channels formed", @@ -1710,7 +1847,7 @@ SilcServerEntry silc_server_new_server(SilcServer server, /* Add again the entry to the ID cache. */ silc_idcache_add(local ? server->local_list->servers : server->global_list->servers, server_name, server_id, - new_server, FALSE); + new_server, 0, NULL); /* Distribute the information about new server in the SILC network to our router. If we are normal server we won't send anything @@ -1782,7 +1919,7 @@ static void silc_server_new_id_real(SilcServer server, packet->src_id_type != SILC_ID_SERVER) return; - idp = silc_id_payload_parse(buffer); + idp = silc_id_payload_parse(buffer->data, buffer->len); if (!idp) return; @@ -1823,12 +1960,13 @@ static void silc_server_new_id_real(SilcServer server, router = silc_idlist_find_server_by_id(server->local_list, sender_id, TRUE, NULL); silc_free(sender_id); - if (!router) - goto out; router_sock = sock; id_list = server->global_list; } + if (!router) + goto out; + switch(id_type) { case SILC_ID_CLIENT: { @@ -1856,7 +1994,7 @@ static void silc_server_new_id_real(SilcServer server, global list. Cell wide information however is kept in the local list. */ entry = silc_idlist_add_client(id_list, NULL, NULL, NULL, - id, router, NULL); + id, router, NULL, 0); if (!entry) { SILC_LOG_ERROR(("Could not add new client to the ID Cache")); @@ -2059,7 +2197,8 @@ void silc_server_new_channel(SilcServer server, return; /* Parse the channel payload */ - payload = silc_channel_payload_parse(packet->buffer); + payload = silc_channel_payload_parse(packet->buffer->data, + packet->buffer->len); if (!payload) return; @@ -2094,7 +2233,7 @@ void silc_server_new_channel(SilcServer server, sock->hostname)); silc_idlist_add_channel(server->global_list, strdup(channel_name), - 0, channel_id, sock->user_data, NULL, NULL); + 0, channel_id, sock->user_data, NULL, NULL, 0); server->stat.channels++; } } else { @@ -2147,6 +2286,8 @@ void silc_server_new_channel(SilcServer server, channel->mode = silc_channel_get_mode(payload); /* Send the new channel key to the server */ + id = silc_id_id2str(channel->id, SILC_ID_CHANNEL); + id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL); chk = silc_channel_key_payload_encode(id_len, id, strlen(channel->channel_key-> cipher->name), @@ -2163,9 +2304,6 @@ void silc_server_new_channel(SilcServer server, We also create a new key for the channel. */ SilcBuffer users = NULL, users_modes = NULL; - if (!channel->id) - channel->id = silc_id_dup(channel_id, SILC_ID_CHANNEL); - if (!SILC_ID_CHANNEL_COMPARE(channel_id, channel->id)) { /* They don't match, send CHANNEL_CHANGE notify to the server to force the ID change. */ @@ -2182,7 +2320,8 @@ void silc_server_new_channel(SilcServer server, silc_server_send_notify_cmode(server, sock, FALSE, channel, channel->mode, server->id, SILC_ID_SERVER, - channel->cipher, channel->hmac_name); + channel->cipher, channel->hmac_name, + channel->passphrase); } /* Create new key for the channel and send it to the server and @@ -2195,8 +2334,8 @@ void silc_server_new_channel(SilcServer server, /* Send to the channel */ silc_server_send_channel_key(server, sock, channel, FALSE); id = silc_id_id2str(channel->id, SILC_ID_CHANNEL); - id_len = SILC_ID_CHANNEL_LEN; - + id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL); + /* Send to the server */ chk = silc_channel_key_payload_encode(id_len, id, strlen(channel->channel_key-> @@ -2344,7 +2483,8 @@ void silc_server_key_agreement(SilcServer server, /* Relay the packet */ silc_server_relay_packet(server, dst_sock, idata->send_key, - idata->hmac_send, packet, FALSE); + idata->hmac_send, idata->psn_send++, + packet, FALSE); } /* Received connection auth request packet that is used during connection @@ -2359,10 +2499,10 @@ void silc_server_connection_auth_request(SilcServer server, SilcSocketConnection sock, SilcPacketContext *packet) { - SilcServerConfigSectionClientConnection *client = NULL; + SilcServerConfigClient *client = NULL; uint16 conn_type; - int ret, port; - SilcAuthMethod auth_meth; + int ret; + SilcAuthMethod auth_meth = SILC_AUTH_NONE; SILC_LOG_DEBUG(("Start")); @@ -2382,21 +2522,21 @@ void silc_server_connection_auth_request(SilcServer server, /* Get the authentication method for the client */ auth_meth = SILC_AUTH_NONE; - port = server->sockets[server->sock]->port; /* Listenning port */ - client = silc_server_config_find_client_conn(server->config, - sock->ip, - port); + client = silc_server_config_find_client(server, sock->ip); if (!client) - client = silc_server_config_find_client_conn(server->config, - sock->hostname, - port); - if (client) - auth_meth = client->auth_meth; - + client = silc_server_config_find_client(server, sock->hostname); + if (client) { + if (client->passphrase) { + if (client->publickey && !server->config->prefer_passphrase_auth) + auth_meth = SILC_AUTH_PUBLIC_KEY; + else + auth_meth = SILC_AUTH_PASSWORD; + } else if (client->publickey) + auth_meth = SILC_AUTH_PUBLIC_KEY; + } + /* Send it back to the client */ - silc_server_send_connection_auth_request(server, sock, - conn_type, - auth_meth); + silc_server_send_connection_auth_request(server, sock, conn_type, auth_meth); } /* Received REKEY packet. The sender of the packet wants to regenerate @@ -2430,3 +2570,36 @@ void silc_server_rekey(SilcServer server, /* Run the protocol */ silc_protocol_execute(protocol, server->schedule, 0, 0); } + +/* Received file transger packet. This packet is never for us. It is to + the client in the packet's destination ID. Sending of this sort of packet + equals sending private message, ie. it is sent point to point from + one client to another. */ + +void silc_server_ftp(SilcServer server, + SilcSocketConnection sock, + SilcPacketContext *packet) +{ + SilcSocketConnection dst_sock; + SilcIDListData idata; + + SILC_LOG_DEBUG(("Start")); + + if (packet->src_id_type != SILC_ID_CLIENT || + packet->dst_id_type != SILC_ID_CLIENT) + return; + + if (!packet->dst_id) + return; + + /* Get the route to the client */ + dst_sock = silc_server_get_client_route(server, packet->dst_id, + packet->dst_id_len, NULL, &idata); + if (!dst_sock) + return; + + /* Relay the packet */ + silc_server_relay_packet(server, dst_sock, idata->send_key, + idata->hmac_send, idata->psn_send++, + packet, FALSE); +}