client-common.c revision 7cb128dc4cae2a03a742f63ba7afee23c78e3af0
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic unsigned int clients_count = 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void client_idle_disconnect_timeout(struct client *client)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int secs;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen user_reason = "Timeout while finishing login.";
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Timeout while finishing login (waited %u secs)", secs);
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen "Disconnected for inactivity during authentication.";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "Disconnected: Inactivity during authentication";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen user_reason = "Timeout while finishing login.";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "proxy: Logging in to %s:%u timed out "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "(state=%u, duration=%us)",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_notify_disconnect(client, CLIENT_DISCONNECT_TIMEOUT, user_reason);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenstatic void client_open_streams(struct client *client)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen i_stream_create_fd(client->fd, LOGIN_MAX_INBUF_SIZE, FALSE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen o_stream_create_fd(client->fd, LOGIN_MAX_OUTBUF_SIZE, FALSE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen o_stream_set_no_error_handling(client->output, TRUE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (iostream_rawlog_create(login_rawlog_dir, &client->input,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic bool client_is_trusted(struct client *client)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *const *net;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int bits;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (client->set->login_trusted_networks == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen net = t_strsplit_spaces(client->set->login_trusted_networks, ", ");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (net_parse_range(*net, &net_ip, &bits) < 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (net_is_in_network(&client->ip, &net_ip, bits))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct master_service_ssl_settings *ssl_set,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct ip_addr *local_ip, const struct ip_addr *remote_ip)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen client = login_binary->client_vfuncs->alloc(pool);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen client->v.auth_send_challenge = client_auth_send_challenge;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->v.auth_parse_response = client_auth_parse_response;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->real_local_ip = client->local_ip = *local_ip;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->real_remote_ip = client->ip = *remote_ip;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid client_destroy(struct client *client, const char *reason)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!client->login_success && reason != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_get_extra_disconnect_reason(client), NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!client->login_success && client->ssl_proxy != NULL)
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen master_auth_request_abort(master_auth, client->master_tag);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen dsasl_client_free(&client->proxy_sasl_client);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (client_unref(&client) && initial_service_count == 1) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* as soon as this connection is done with proxying
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen (or whatever), the process will die. there's no need for
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen authentication anymore, so close the connection.
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen do this only with initial service_count=1, in case there
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen are other clients with pending authentications */
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen auth_client_disconnect(auth_client, "unnecessary connection");
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainenvoid client_destroy_success(struct client *client, const char *reason)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid client_destroy_internal_failure(struct client *client)
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen client_notify_disconnect(client, CLIENT_DISCONNECT_INTERNAL_ERROR,
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen "Internal login failure. "
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen "Refer to server log for more information.");
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen "Internal login failure (pid=%s id=%u)",
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen master_service_client_connection_destroyed(master_service);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* we have no clients */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* destroy the last client that hasn't successfully authenticated yet.
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen this is usually the last client, but don't kill it if it's just
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen waiting for master to finish its job. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (client = last_client; client != NULL; client = client->prev) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_notify_disconnect(client, CLIENT_DISCONNECT_RESOURCE_CONSTRAINT,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Connection queue full");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_destroy(client, "Disconnected: Connection queue full");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid clients_destroy_all_reason(const char *reason)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (client = clients; client != NULL; client = next) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen clients_destroy_all_reason("Disconnected: Shutting down");
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainenstatic void client_start_tls(struct client *client)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!client_unref(&client) || client->destroyed)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen fd_ssl = ssl_proxy_alloc(client->fd, &client->ip, client->pool,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "TLS initialization failed.");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "Disconnected: TLS initialization failed.");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ssl_proxy_set_client(client->ssl_proxy, client);
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainenstatic int client_output_starttls(struct client *client)
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen if ((ret = o_stream_flush(client->output)) < 0) {
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen o_stream_unset_flush_callback(client->output);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid client_cmd_starttls(struct client *client)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->v.notify_starttls(client, FALSE, "TLS is already active.");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->v.notify_starttls(client, FALSE, "TLS support isn't enabled.");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* remove input handler, SSL proxy gives us a new fd. we also have to
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen remove it in case we have to wait for buffer to be flushed */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->v.notify_starttls(client, TRUE, "Begin TLS negotiation now.");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* uncork the old fd */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* the buffer has to be flushed */
4182d8cd818e76856a5a1e25b343fe5ddf69fd8eTimo Sirainen o_stream_set_flush_pending(client->output, TRUE);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenunsigned int clients_get_count(void)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenconst char *client_get_session_id(struct client *client)
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen unsigned int i;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 24);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen base64_buf = buffer_create_dynamic(pool_datastack_create(), 24*2);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen timestamp = tv.tv_usec + (long long)tv.tv_sec * 1000ULL*1000ULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* add lowest 48 bits of the timestamp. this gives us a bit less than
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen 9 years until it wraps */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append_c(buf, (timestamp >> i) & 0xff);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append_c(buf, client->remote_port & 0xff);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append_c(buf, (client->remote_port >> 16) & 0xff);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append(buf, &client->ip.u.ip6, sizeof(client->ip.u.ip6));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buffer_append(buf, &client->ip.u.ip4, sizeof(client->ip.u.ip4));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen base64_encode(buf->data, buf->used, base64_buf);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->session_id = p_strdup(client->pool, str_c(base64_buf));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic struct var_expand_table login_var_expand_empty_tab[] = {
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainenget_var_expand_users(struct var_expand_table *tab, const char *user)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int i;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = 0; i < 3; i++)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen tab[i].value = str_sanitize(tab[i].value, 80);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic const struct var_expand_table *
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab = t_malloc(sizeof(login_var_expand_empty_tab));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen get_var_expand_users(tab, client->virtual_user);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[5].value = net_ip2addr(&client->local_ip);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[8].value = client->auth_mech_name == NULL ? NULL :
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[11].value = client->secured ? "secured" : NULL;
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen tab[11].value = ssl_error == NULL ? ssl_state :
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen t_strdup_printf("%s: %s", ssl_state, ssl_error);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ssl_proxy_get_security_string(client->ssl_proxy);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[14].value = client_get_session_id(client);
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen tab[15].value = net_ip2addr(&client->real_local_ip);
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen tab[16].value = net_ip2addr(&client->real_remote_ip);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen tab[17].value = dec2str(client->real_local_port);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen tab[18].value = dec2str(client->real_remote_port);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen get_var_expand_users(tab+19, client->virtual_user_orig);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen get_var_expand_users(tab+22, client->virtual_auth_user);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenstatic const char *
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenclient_get_log_str(struct client *client, const char *msg)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen static struct var_expand_table static_tab[3] = {
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen const struct var_expand_table *var_expand_table;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen char *const *e;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int pos;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen var_expand_table = get_var_expand_table(client);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen for (e = client->set->log_format_elements_split; *e != NULL; e++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* username is added even if it's empty */
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen var_expand(str2, *e, login_var_expand_empty_tab);
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen if (strcmp(str_c(str)+pos, str_c(str2)) == 0) {
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen /* empty %variables, don't add */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen var_expand(str, client->set->login_log_format, tab);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid client_log(struct client *client, const char *msg)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_info("%s", client_get_log_str(client, msg));
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid client_log_err(struct client *client, const char *msg)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_error("%s", client_get_log_str(client, msg));
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenvoid client_log_warn(struct client *client, const char *msg)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen i_warning("%s", client_get_log_str(client, msg));
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenbool client_is_tls_enabled(struct client *client)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return ssl_initialized && strcmp(client->ssl_set->ssl, "no") != 0;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenconst char *client_get_extra_disconnect_reason(struct client *client)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen unsigned int auth_secs = client->auth_first_started == 0 ? 0 :
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (client->set->auth_ssl_require_client_cert &&
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (ssl_proxy_has_broken_client_cert(client->ssl_proxy))
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(client sent an invalid cert)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (!ssl_proxy_has_valid_client_cert(client->ssl_proxy))
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(client didn't send a cert)";
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen "(disconnected before auth was ready, waited %u secs)",
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen (unsigned int)(ioloop_time - client->created));
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(no auth attempts in %u secs)",
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen (unsigned int)(ioloop_time - client->created));
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* some auth attempts without SSL/TLS */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(tried to use disallowed plaintext auth)";
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (client->set->auth_ssl_require_client_cert &&
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(cert required, client didn't start TLS)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(tried to use unsupported auth mechanism)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (client->auth_waiting && client->auth_attempts == 1) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(client didn't finish SASL auth, "
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (client->auth_request != NULL && client->auth_attempts == 1) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(disconnected while authenticating, "
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen if (client->authenticating && client->auth_attempts == 1) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(disconnected while finishing login, "
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen if (client->auth_try_aborted && client->auth_attempts == 1)
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen return "(aborted authentication)";
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen return "(auth process communication failure)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(proxy dest auth failed)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(internal failure, %u successful auths)",
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(user disabled)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(password expired)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(auth failed, %u attempts in %u secs)",
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainenvoid client_notify_disconnect(struct client *client,
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen client->v.notify_disconnect(client, reason, text);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenvoid client_notify_auth_ready(struct client *client)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenvoid client_notify_status(struct client *client, bool bad, const char *text)
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainenvoid client_send_raw_data(struct client *client, const void *data, size_t size)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen ret = o_stream_send(client->output, data, size);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* either disconnection or buffer full. in either case we want
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen this connection destroyed. however destroying it here might
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen break things if client is still tried to be accessed without
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen being referenced.. */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid client_send_raw(struct client *client, const char *data)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen client_send_raw_data(client, data, strlen(data));
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen /* buffer full */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen "Input buffer full, aborting");
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen client_destroy(client, "Disconnected: Input buffer full");
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* disconnected */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* nothing new read */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* something was read */