From: Timo Sirainen Date: Sun, 12 Dec 2021 22:56:12 +0000 (+0200) Subject: lib-master, global: Replace master_service_anvil_send() with explicit connect/disconn... X-Git-Tag: 2.4.0~4542 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=faf7b2c658b92731cc6e2861fb8b2065aaff82d7;p=thirdparty%2Fdovecot%2Fcore.git lib-master, global: Replace master_service_anvil_send() with explicit connect/disconnect() --- diff --git a/src/imap-hibernate/imap-client.c b/src/imap-hibernate/imap-client.c index 4713de455a..8ae59240df 100644 --- a/src/imap-hibernate/imap-client.c +++ b/src/imap-hibernate/imap-client.c @@ -565,14 +565,6 @@ static void imap_client_io_deactivate_user(struct imap_client *client ATTR_UNUSE i_set_failure_prefix("imap-hibernate: "); } -static const char *imap_client_get_anvil_userip_ident(struct imap_client_state *state) -{ - if (state->remote_ip.family == 0) - return NULL; - return t_strconcat(net_ip2addr(&state->remote_ip), "/", - str_tabescape(state->username), NULL); -} - struct imap_client * imap_client_create(int fd, const struct imap_client_state *state) { @@ -583,7 +575,7 @@ imap_client_create(int fd, const struct imap_client_state *state) struct imap_client *client; pool_t pool = pool_alloconly_create("imap client", 256); void *statebuf; - const char *ident, *error; + const char *error; i_assert(state->username != NULL); i_assert(state->mail_log_prefix != NULL); @@ -638,12 +630,13 @@ imap_client_create(int fd, const struct imap_client_state *state) client->log_prefix = p_strdup(pool, str_c(str)); } T_END; - ident = imap_client_get_anvil_userip_ident(&client->state); - if (ident != NULL) { - if (master_service_anvil_send(master_service, t_strconcat( - "CONNECT\t", my_pid, "\timap/", ident, "\n", NULL))) - client->state.anvil_sent = TRUE; - } + struct master_service_anvil_session anvil_session = { + .username = client->state.username, + .service_name = "imap", + .ip = client->state.remote_ip, + }; + if (master_service_anvil_connect(master_service, &anvil_session)) + client->state.anvil_sent = TRUE; p_array_init(&client->notifys, pool, 2); DLLIST_PREPEND(&imap_clients, client); @@ -685,10 +678,12 @@ void imap_client_destroy(struct imap_client **_client, const char *reason) } if (client->state.anvil_sent) { - master_service_anvil_send(master_service, t_strconcat( - "DISCONNECT\t", my_pid, "\timap/", - imap_client_get_anvil_userip_ident(&client->state), - "\n", NULL)); + struct master_service_anvil_session anvil_session = { + .username = client->state.username, + .service_name = "imap", + .ip = client->state.remote_ip, + }; + master_service_anvil_disconnect(master_service, &anvil_session); } if (client->master_conn != NULL) diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c index 5592b51db1..d842d6c765 100644 --- a/src/imap/imap-client.c +++ b/src/imap/imap-client.c @@ -118,7 +118,6 @@ struct client *client_create(int fd_in, int fd_out, { const struct mail_storage_settings *mail_set; struct client *client; - const char *ident; pool_t pool; /* always use nonblocking I/O */ @@ -203,12 +202,10 @@ struct client *client_create(int fd_in, int fd_out, client_add_capability(client, "SPECIAL-USE"); } - ident = mail_user_get_anvil_userip_ident(client->user); - if (ident != NULL) { - if (master_service_anvil_send(master_service, t_strconcat( - "CONNECT\t", my_pid, "\timap/", ident, "\n", NULL))) - client->anvil_sent = TRUE; - } + struct master_service_anvil_session anvil_session; + mail_user_get_anvil_session(client->user, &anvil_session); + if (master_service_anvil_connect(master_service, &anvil_session)) + client->anvil_sent = TRUE; imap_client_count++; DLLIST_PREPEND(&imap_clients, client); @@ -493,10 +490,9 @@ static void client_default_destroy(struct client *client, const char *reason) if (client->mailbox != NULL) imap_client_close_mailbox(client); if (client->anvil_sent) { - master_service_anvil_send(master_service, t_strconcat( - "DISCONNECT\t", my_pid, "\timap/", - mail_user_get_anvil_userip_ident(client->user), - "\n", NULL)); + struct master_service_anvil_session anvil_session; + mail_user_get_anvil_session(client->user, &anvil_session); + master_service_anvil_disconnect(master_service, &anvil_session); } if (client->free_parser != NULL) diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c index fcad691093..f47f7d8a09 100644 --- a/src/lib-master/master-service.c +++ b/src/lib-master/master-service.c @@ -8,6 +8,7 @@ #include "hostpid.h" #include "path-util.h" #include "array.h" +#include "str.h" #include "strescape.h" #include "env-util.h" #include "home-expand.h" @@ -920,7 +921,8 @@ bool master_service_is_master_stopped(struct master_service *service) (service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0; } -bool master_service_anvil_send(struct master_service *service, const char *cmd) +static bool +master_service_anvil_send(struct master_service *service, const char *cmd) { ssize_t ret; @@ -945,6 +947,40 @@ bool master_service_anvil_send(struct master_service *service, const char *cmd) } } +static void +master_service_anvil_session_to_cmd(string_t *cmd, + const struct master_service_anvil_session *session) +{ + str_printfa(cmd, "%s\t", my_pid); + str_append_tabescaped(cmd, session->service_name); + if (session->ip.family != 0) { + str_append_c(cmd, '/'); + str_append(cmd, net_ip2addr(&session->ip)); + } + str_append_c(cmd, '/'); + str_append_tabescaped(cmd, session->username); +} + +bool master_service_anvil_connect(struct master_service *service, + const struct master_service_anvil_session *session) +{ + string_t *cmd = t_str_new(128); + str_append(cmd, "CONNECT\t"); + master_service_anvil_session_to_cmd(cmd, session); + str_append_c(cmd, '\n'); + return master_service_anvil_send(service, str_c(cmd)); +} + +void master_service_anvil_disconnect(struct master_service *service, + const struct master_service_anvil_session *session) +{ + string_t *cmd = t_str_new(128); + str_append(cmd, "DISCONNECT\t"); + master_service_anvil_session_to_cmd(cmd, session); + str_append_c(cmd, '\n'); + (void)master_service_anvil_send(service, str_c(cmd)); +} + void master_service_client_connection_created(struct master_service *service) { i_assert(service->master_status.available_count > 0); diff --git a/src/lib-master/master-service.h b/src/lib-master/master-service.h index efb90d4b7f..4c065bb91f 100644 --- a/src/lib-master/master-service.h +++ b/src/lib-master/master-service.h @@ -92,6 +92,12 @@ struct master_service_connection { bool accepted:1; }; +struct master_service_anvil_session { + const char *username; + const char *service_name; + struct ip_addr ip; +}; + typedef void master_service_connection_callback_t(struct master_service_connection *conn); @@ -225,9 +231,13 @@ bool master_service_is_killed(struct master_service *service); standalone. */ bool master_service_is_master_stopped(struct master_service *service); -/* Send command to anvil process, if we have fd to it. Returns TRUE if it was - successfully sent. */ -bool master_service_anvil_send(struct master_service *service, const char *cmd); +/* Send CONNECT command to anvil process, if it's still connected. + Returns TRUE if it was successfully sent. */ +bool master_service_anvil_connect(struct master_service *service, + const struct master_service_anvil_session *session); +/* Send DISCONNECT command to anvil process, if it's still connected. */ +void master_service_anvil_disconnect(struct master_service *service, + const struct master_service_anvil_session *session); /* Call to accept the client connection. Otherwise the connection is closed. */ void master_service_client_connection_accept(struct master_service_connection *conn); /* Used to create "extra client connections" outside the common accept() diff --git a/src/lib-storage/mail-user.c b/src/lib-storage/mail-user.c index 9cf60424a5..85cd355187 100644 --- a/src/lib-storage/mail-user.c +++ b/src/lib-storage/mail-user.c @@ -640,12 +640,14 @@ int mail_user_lock_file_create(struct mail_user *user, const char *lock_fname, return mail_storage_lock_create(path, &lock_set, mail_set, lock_r, error_r); } -const char *mail_user_get_anvil_userip_ident(struct mail_user *user) +void mail_user_get_anvil_session(struct mail_user *user, + struct master_service_anvil_session *session_r) { - if (user->conn.remote_ip == NULL) - return NULL; - return t_strconcat(net_ip2addr(user->conn.remote_ip), "/", - str_tabescape(user->username), NULL); + i_zero(session_r); + session_r->username = user->username; + session_r->service_name = master_service_get_name(master_service); + if (user->conn.remote_ip != NULL) + session_r->ip = *user->conn.remote_ip; } static void diff --git a/src/lib-storage/mail-user.h b/src/lib-storage/mail-user.h index ef833d1bd1..f442d9396a 100644 --- a/src/lib-storage/mail-user.h +++ b/src/lib-storage/mail-user.h @@ -10,6 +10,7 @@ struct module; struct stats; struct fs_settings; struct ssl_iostream_settings; +struct master_service_anvil_session; struct mail_user; struct dict_op_settings; @@ -200,8 +201,9 @@ void mail_user_drop_useless_namespaces(struct mail_user *user); const char *mail_user_home_expand(struct mail_user *user, const char *path); /* Returns 0 if ok, -1 if home directory isn't set. */ int mail_user_try_home_expand(struct mail_user *user, const char **path); -/* Returns unique user+ip identifier for anvil. */ -const char *mail_user_get_anvil_userip_ident(struct mail_user *user); +/* Fill out anvil session struct for the user session. */ +void mail_user_get_anvil_session(struct mail_user *user, + struct master_service_anvil_session *session_r); /* Basically the same as mail_storage_find_class(), except automatically load storage plugins when needed. */ diff --git a/src/lmtp/lmtp-local.c b/src/lmtp/lmtp-local.c index 202fbb2c4f..7c685553da 100644 --- a/src/lmtp/lmtp-local.c +++ b/src/lmtp/lmtp-local.c @@ -97,9 +97,11 @@ lmtp_local_rcpt_anvil_disconnect(struct lmtp_local_recipient *llrcpt) llrcpt->anvil_connect_sent = FALSE; input = mail_storage_service_user_get_input(llrcpt->service_user); - master_service_anvil_send(master_service, t_strconcat( - "DISCONNECT\t", my_pid, "\t", master_service_get_name(master_service), - "/", input->username, "\n", NULL)); + struct master_service_anvil_session anvil_session = { + .username = input->username, + .service_name = master_service_get_name(master_service), + }; + master_service_anvil_disconnect(master_service, &anvil_session); } static void @@ -274,9 +276,11 @@ lmtp_local_rcpt_anvil_cb(const char *reply, void *context) "Too many concurrent deliveries for user"); } else if (lmtp_local_rcpt_anvil_finish(llrcpt)) { input = mail_storage_service_user_get_input(llrcpt->service_user); - if (master_service_anvil_send(master_service, t_strconcat( - "CONNECT\t", my_pid, "\t", master_service_get_name(master_service), - "/", input->username, "\n", NULL))) + struct master_service_anvil_session anvil_session = { + .username = input->username, + .service_name = master_service_get_name(master_service), + }; + if (master_service_anvil_connect(master_service, &anvil_session)) llrcpt->anvil_connect_sent = TRUE; } } diff --git a/src/pop3/pop3-client.c b/src/pop3/pop3-client.c index e0c8c589a3..09d927175f 100644 --- a/src/pop3/pop3-client.c +++ b/src/pop3/pop3-client.c @@ -448,7 +448,7 @@ void client_create_finish(struct client *client) int client_init_mailbox(struct client *client, const char **error_r) { enum mailbox_flags flags; - const char *ident, *errmsg; + const char *errmsg; /* refresh proctitle before a potentially long-running init_mailbox() */ pop3_refresh_proctitle(); @@ -473,12 +473,10 @@ int client_init_mailbox(struct client *client, const char **error_r) if (!client->set->pop3_no_flag_updates && client->messages_count > 0) client->seen_bitmask = i_malloc(MSGS_BITMASK_SIZE(client)); - ident = mail_user_get_anvil_userip_ident(client->user); - if (ident != NULL) { - if (master_service_anvil_send(master_service, t_strconcat( - "CONNECT\t", my_pid, "\tpop3/", ident, "\n", NULL))) - client->anvil_sent = TRUE; - } + struct master_service_anvil_session anvil_session; + mail_user_get_anvil_session(client->user, &anvil_session); + if (master_service_anvil_connect(master_service, &anvil_session)) + client->anvil_sent = TRUE; return 0; } @@ -604,10 +602,9 @@ static void client_default_destroy(struct client *client, const char *reason) if (client->mailbox != NULL) mailbox_free(&client->mailbox); if (client->anvil_sent) { - master_service_anvil_send(master_service, t_strconcat( - "DISCONNECT\t", my_pid, "\tpop3/", - mail_user_get_anvil_userip_ident(client->user), - "\n", NULL)); + struct master_service_anvil_session anvil_session; + mail_user_get_anvil_session(client->user, &anvil_session); + master_service_anvil_disconnect(master_service, &anvil_session); } if (client->session_dotlock != NULL) diff --git a/src/submission/submission-client.c b/src/submission/submission-client.c index a0f0a0efa3..a2d1914413 100644 --- a/src/submission/submission-client.c +++ b/src/submission/submission-client.c @@ -186,7 +186,6 @@ client_create(int fd_in, int fd_out, struct mail_user *user, set->parsed_workarounds; const struct mail_storage_settings *mail_set; struct smtp_server_settings smtp_set; - const char *ident; struct client *client; pool_t pool; @@ -249,14 +248,10 @@ client_create(int fd_in, int fd_out, struct mail_user *user, submission_client_count++; DLLIST_PREPEND(&submission_clients, client); - ident = mail_user_get_anvil_userip_ident(client->user); - if (ident != NULL) { - if (master_service_anvil_send( - master_service, t_strconcat( - "CONNECT\t", my_pid, "\tsubmission/", ident, - "\n", NULL))) - client->anvil_sent = TRUE; - } + struct master_service_anvil_session anvil_session; + mail_user_get_anvil_session(client->user, &anvil_session); + if (master_service_anvil_connect(master_service, &anvil_session)) + client->anvil_sent = TRUE; if (hook_client_created != NULL) hook_client_created(&client); @@ -316,11 +311,9 @@ client_default_destroy(struct client *client) DLLIST_REMOVE(&submission_clients, client); if (client->anvil_sent) { - master_service_anvil_send( - master_service, t_strconcat( - "DISCONNECT\t", my_pid, "\tsubmission/", - mail_user_get_anvil_userip_ident(client->user), - "\n", NULL)); + struct master_service_anvil_session anvil_session; + mail_user_get_anvil_session(client->user, &anvil_session); + master_service_anvil_disconnect(master_service, &anvil_session); } if (client->urlauth_ctx != NULL)