From c35b7bec7110142b530d976fbe5a7368bcbf4e05 Mon Sep 17 00:00:00 2001 From: Dmitry Simonenko Date: Thu, 8 Jun 2017 15:36:21 +0300 Subject: [PATCH] odissey: send client errors --- src/od_auth.c | 12 ++++++++++++ src/od_frontend.c | 32 +++++++++++++++++++++++++++----- src/od_frontend.h | 1 + src/od_router.c | 2 +- src/od_router.h | 3 ++- src/od_tls.c | 5 +++++ 6 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/od_auth.c b/src/od_auth.c index 73cf6879..c089bc7b 100644 --- a/src/od_auth.c +++ b/src/od_auth.c @@ -91,6 +91,8 @@ od_auth_frontend_cleartext(od_client_t *client) if (rc == -1) { od_error_client(&instance->log, client->id, "auth", "password read error"); + od_frontend_error(client, SO_ERROR_PROTOCOL_VIOLATION, + "bad password message"); so_password_free(&client_token); return -1; } @@ -108,6 +110,8 @@ od_auth_frontend_cleartext(od_client_t *client) od_log_client(&instance->log, client->id, "auth", "user '%s' incorrect password", client->startup.user); + od_frontend_error(client, SO_ERROR_INVALID_PASSWORD, + "incorrect password"); return -1; } return 0; @@ -162,6 +166,8 @@ od_auth_frontend_md5(od_client_t *client) if (rc == -1) { od_error_client(&instance->log, client->id, "auth", "password read error"); + od_frontend_error(client, SO_ERROR_PROTOCOL_VIOLATION, + "bad password message"); so_password_free(&client_token); return -1; } @@ -191,6 +197,8 @@ od_auth_frontend_md5(od_client_t *client) od_log_client(&instance->log, client->id, "auth", "user '%s' incorrect password", client->startup.user); + od_frontend_error(client, SO_ERROR_INVALID_PASSWORD, + "incorrect password"); return -1; } return 0; @@ -211,6 +219,8 @@ int od_auth_frontend(od_client_t *client) od_error_client(&instance->log, client->id, "auth" "user '%s' not found", so_parameter_value(client->startup.user)); + od_frontend_error(client, SO_ERROR_INVALID_AUTHORIZATION_SPECIFICATION, + "unknown user"); return -1; } } @@ -221,6 +231,8 @@ int od_auth_frontend(od_client_t *client) od_log_client(&instance->log, client->id, "auth", "user '%s' access denied", so_parameter_value(client->startup.user)); + od_frontend_error(client, SO_ERROR_INVALID_AUTHORIZATION_SPECIFICATION, + "user access denied"); return -1; } diff --git a/src/od_frontend.c b/src/od_frontend.c index 9e137649..968d7f30 100644 --- a/src/od_frontend.c +++ b/src/od_frontend.c @@ -95,7 +95,7 @@ od_frontend_startup_read(od_client_t *client) break; if (to_read == -1) { od_error_client(&instance->log, client->id, "startup", - "bad startup packet"); + "failed to read startup packet, closing"); return -1; } int rc = so_stream_ensure(stream, to_read); @@ -128,7 +128,7 @@ od_frontend_startup(od_client_t *client) stream->s, so_stream_used(stream)); if (rc == -1) - return -1; + goto error; /* client ssl request */ rc = od_tls_frontend_accept(client, &instance->log, @@ -150,8 +150,15 @@ od_frontend_startup(od_client_t *client) stream->s, so_stream_used(stream)); if (rc == -1) - return -1; + goto error; return 0; + +error: + od_error_client(&instance->log, client->id, "startup", + "incorrect startup packet"); + od_frontend_error(client, SO_ERROR_PROTOCOL_VIOLATION, + "bad startup packet"); + return -1; } static inline void @@ -459,12 +466,23 @@ void od_frontend(void *arg) case OD_RERROR: od_error_client(&instance->log, client->id, NULL, "routing failed, closing"); + od_frontend_error(client, SO_ERROR_SYSTEM_ERROR, + "client routing failed"); od_frontend_close(client); return; case OD_RERROR_NOT_FOUND: od_error_client(&instance->log, client->id, NULL, "database route '%s' is not declared, closing", so_parameter_value(client->startup.database)); + od_frontend_error(client, SO_ERROR_UNDEFINED_DATABASE, + "database route is not declared"); + od_frontend_close(client); + return; + case OD_RERROR_TIMEDOUT: + od_error_client(&instance->log, client->id, NULL, + "route connection timedout, closing"); + od_frontend_error(client, SO_ERROR_TOO_MANY_CONNECTIONS, + "connection timedout"); od_frontend_close(client); return; case OD_RERROR_LIMIT: @@ -492,6 +510,8 @@ void od_frontend(void *arg) case OD_RS_EATTACH: assert(server == NULL); assert(client->route != NULL); + od_frontend_error(client, SO_ERROR_CONNECTION_FAILURE, + "failed to get remote server connection"); /* detach client from route */ od_unroute(client); break; @@ -536,7 +556,8 @@ void od_frontend(void *arg) od_log_server(&instance->log, server->id, NULL, "disconnected (server configure error): %s", machine_error(server->io)); - + od_frontend_error(client, SO_ERROR_CONNECTION_FAILURE, + "failed to configure remote server"); /* close backend connection */ od_router_close_and_unroute(client); break; @@ -547,7 +568,8 @@ void od_frontend(void *arg) od_log_server(&instance->log, server->id, NULL, "disconnected (read/write error): %s", machine_error(server->io)); - + od_frontend_error(client, SO_ERROR_CONNECTION_FAILURE, + "remote server read/write error"); /* close backend connection */ od_router_close_and_unroute(client); break; diff --git a/src/od_frontend.h b/src/od_frontend.h index 0303b734..f1746b51 100644 --- a/src/od_frontend.h +++ b/src/od_frontend.h @@ -7,6 +7,7 @@ * PostgreSQL connection pooler and request router. */ +int od_frontend_error(od_client_t*, char*, char*, ...); void od_frontend(void*); #endif /* OD_FRONTEND_H */ diff --git a/src/od_router.c b/src/od_router.c index 00e8f1e7..5350456b 100644 --- a/src/od_router.c +++ b/src/od_router.c @@ -157,7 +157,7 @@ od_router_attacher(void *arg) if (rc < 0) { od_debug_client(&instance->log, client->id, "router", "server pool wait timedout, closing"); - msg_attach->status = OD_RERROR; + msg_attach->status = OD_RERROR_TIMEDOUT; machine_queue_put(msg_attach->response, msg); return; } diff --git a/src/od_router.h b/src/od_router.h index 03b3dbef..43da6e93 100644 --- a/src/od_router.h +++ b/src/od_router.h @@ -14,7 +14,8 @@ typedef enum OD_ROK, OD_RERROR, OD_RERROR_NOT_FOUND, - OD_RERROR_LIMIT + OD_RERROR_LIMIT, + OD_RERROR_TIMEDOUT } od_routerstatus_t; struct od_router diff --git a/src/od_tls.c b/src/od_tls.c index 5f3315d5..0a902a69 100644 --- a/src/od_tls.c +++ b/src/od_tls.c @@ -43,6 +43,7 @@ #include "od_pooler.h" #include "od_relay.h" #include "od_tls.h" +#include "od_frontend.h" machine_tls_t od_tls_frontend(od_scheme_t *scheme) @@ -106,6 +107,8 @@ od_tls_frontend_accept(od_client_t *client, return -1; } od_log_client(log, client->id, "tls", "disabled, closing"); + od_frontend_error(client, SO_ERROR_FEATURE_NOT_SUPPORTED, + "SSL is not supported"); return -1; } /* supported 'S' */ @@ -131,6 +134,8 @@ od_tls_frontend_accept(od_client_t *client, break; default: od_log_client(log, client->id, "tls", "required, closing"); + od_frontend_error(client, SO_ERROR_PROTOCOL_VIOLATION, + "SSL is required"); return -1; } return 0;