+ SilcList list;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcClientEntry client = NULL;
+ SilcIDListData idata;
+ SilcPacketStream sock;
+ SilcServerEntry *routed = NULL;
+ SilcUInt32 routed_count = 0;
+ SilcBool gone = FALSE;
+ int k;
+
+ SILC_LOG_DEBUG(("Sending %s packet to operators",
+ silc_get_packet_name(type)));
+
+ /* If local was requested send only locally connected operators. */
+ if (local || (server->server_type == SILC_SERVER && !route)) {
+ if (!silc_idcache_get_all(server->local_list->clients, &list))
+ return;
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ client = (SilcClientEntry)id_cache->context;
+ if (!client->router && SILC_IS_LOCAL(client) &&
+ (client->mode & SILC_UMODE_SERVER_OPERATOR ||
+ client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
+
+ /* Send the packet to locally connected operator */
+ silc_server_packet_send_dest(server, client->connection, type, flags,
+ client->id, SILC_ID_CLIENT,
+ data, data_len);
+ }
+ }
+ return;
+ }
+
+ if (!silc_idcache_get_all(server->local_list->clients, &list))
+ return;
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ client = (SilcClientEntry)id_cache->context;
+ if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
+ !(client->mode & SILC_UMODE_ROUTER_OPERATOR))
+ continue;
+
+ if (server->server_type != SILC_SERVER && client->router &&
+ ((!route && client->router->router == server->id_entry) || route)) {
+
+ /* Check if we have sent the packet to this route already */
+ for (k = 0; k < routed_count; k++)
+ if (routed[k] == client->router)
+ break;
+ if (k < routed_count)
+ continue;
+
+ /* Route only once to router */
+ sock = client->router->connection;
+ idata = silc_packet_get_context(sock);
+ if (idata->conn_type == SILC_CONN_ROUTER) {
+ if (gone)
+ continue;
+ gone = TRUE;
+ }
+
+ /* Send the packet */
+ silc_server_packet_send_dest(server, sock, type, flags,
+ client->id, SILC_ID_CLIENT,
+ data, data_len);
+
+ /* Mark this route routed already */
+ routed = silc_realloc(routed, sizeof(*routed) * (routed_count + 1));
+ routed[routed_count++] = client->router;
+ continue;
+ }
+
+ if (client->router || !client->connection)
+ continue;
+
+ /* Send to locally connected client */
+ sock = client->connection;
+ silc_server_packet_send_dest(server, sock, type, flags,
+ client->id, SILC_ID_CLIENT,
+ data, data_len);
+
+ }
+
+ if (!silc_idcache_get_all(server->global_list->clients, &list))
+ return;
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ client = (SilcClientEntry)id_cache->context;
+ if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
+ !(client->mode & SILC_UMODE_ROUTER_OPERATOR))
+ continue;
+
+ if (server->server_type != SILC_SERVER && client->router &&
+ ((!route && client->router->router == server->id_entry) || route)) {
+
+ /* Check if we have sent the packet to this route already */
+ for (k = 0; k < routed_count; k++)
+ if (routed[k] == client->router)
+ break;
+ if (k < routed_count)
+ continue;
+
+ /* Route only once to router */
+ sock = client->router->connection;
+ idata = silc_packet_get_context(sock);
+ if (idata->conn_type == SILC_CONN_ROUTER) {
+ if (gone)
+ continue;
+ gone = TRUE;
+ }
+
+ /* Send the packet */
+ silc_server_packet_send_dest(server, sock, type, flags,
+ client->id, SILC_ID_CLIENT,
+ data, data_len);
+
+ /* Mark this route routed already */
+ routed = silc_realloc(routed, sizeof(*routed) * (routed_count + 1));
+ routed[routed_count++] = client->router;
+ continue;
+ }
+
+ if (client->router || !client->connection)
+ continue;
+
+ /* Send to locally connected client */
+ sock = client->connection;
+ silc_server_packet_send_dest(server, sock, type, flags,
+ client->id, SILC_ID_CLIENT,
+ data, data_len);