* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) The Exim Maintainers 2020 - 2022 */
+/* Copyright (c) The Exim Maintainers 2020 - 2023 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Functions concerned with retrying unsuccessful deliveries. */
*/
BOOL
-retry_ultimate_address_timeout(uschar *retry_key, const uschar *domain,
+retry_ultimate_address_timeout(const uschar * retry_key, const uschar *domain,
dbdata_retry *retry_record, time_t now)
{
BOOL address_timeout;
+const uschar *
+retry_host_key_build(const host_item * host, BOOL incl_ip,
+ const uschar * portstring)
+{
+const uschar * s = host->name;
+gstring * g = string_is_ip_address(s, NULL)
+ ? string_fmt_append(NULL, "T:[%s]", s) /* wrap a name which is a bare ip */
+ : string_fmt_append(NULL, "T:%s", s);
+
+s = host->address;
+if (incl_ip)
+ g = Ustrchr(s, ':')
+ ? string_fmt_append(g, ":[%s]", s) /* wrap an ipv6 */
+ : string_fmt_append(g, ":%s", s);
+
+if (portstring)
+ g = string_cat(g, portstring);
+
+gstring_release_unused(g);
+return string_from_gstring(g);
+}
+
+
/*************************************************
* Set status of a host+address item *
*************************************************/
BOOL
retry_check_address(const uschar *domain, host_item *host, uschar *portstring,
- BOOL include_ip_address, uschar **retry_host_key, uschar **retry_message_key)
+ BOOL include_ip_address,
+ const uschar **retry_host_key, const uschar **retry_message_key)
{
BOOL yield = FALSE;
time_t now = time(NULL);
-uschar * host_key, * message_key;
+const uschar * host_key, * message_key;
open_db dbblock, * dbm_file;
tree_node * node;
dbdata_retry * host_retry_record, * message_retry_record;
*retry_host_key = *retry_message_key = NULL;
-DEBUG(D_transport|D_retry) debug_printf("checking status of %s\n", host->name);
+DEBUG(D_transport|D_retry) debug_printf("checking retry status of %s\n", host->name);
/* Do nothing if status already set; otherwise initialize status as usable. */
host->status = hstatus_usable;
/* Generate the host key for the unusable tree and the retry database. Ensure
-host names are lower cased (that's what %S does). */
-
-host_key = include_ip_address
- ? string_sprintf("T:%S:%s%s", host->name, host->address, portstring)
- : string_sprintf("T:%S%s", host->name, portstring);
-
-/* Generate the message-specific key */
+host names are lower cased (that's what %S does).
+Generate the message-specific key too.
+Be sure to maintain lack-of-spaces in retry keys; exinext depends on it. */
+host_key = retry_host_key_build(host, include_ip_address, portstring);
message_key = string_sprintf("%s:%s", host_key, message_id);
/* Search the tree of unusable IP addresses. This is filled in when deliveries
*/
void
-retry_add_item(address_item *addr, uschar *key, int flags)
+retry_add_item(address_item * addr, const uschar * key, int flags)
{
retry_item * rti = store_get(sizeof(retry_item), GET_UNTAINTED);
host_item * host = addr->host_used;
*/
retry_config *
-retry_find_config(const uschar *key, const uschar *alternate, int basic_errno,
+retry_find_config(const uschar * key, const uschar * alternate, int basic_errno,
int more_errno)
{
-const uschar *colon = Ustrchr(key, ':');
-retry_config *yield;
+const uschar * colon = Ustrchr(key, ':');
+retry_config * yield;
/* If there's a colon in the key, there are two possibilities:
hostname:ip+port
- In this case, we copy the host name.
+ In this case, we copy the host name (which could be an [ip], including
+ being an [ipv6], and we drop the []).
(2) This is a key for a pipe, file, or autoreply delivery, in the format
if (colon)
key = isalnum(*key)
? string_copyn(key, colon-key) /* the hostname */
+ : *key == '['
+ ? string_copyn(key+1, Ustrchr(key, ']')-1-key) /* the ip */
: Ustrrchr(key, ':') + 1; /* Take from the last colon */
/* Sort out the keys */
*/
void
-retry_update(address_item **addr_defer, address_item **addr_failed,
- address_item **addr_succeed)
+retry_update(address_item ** addr_defer, address_item ** addr_failed,
+ address_item ** addr_succeed)
{
open_db dbblock;
open_db *dbm_file = NULL;
for (int i = 0; i < 3; i++)
{
- address_item *endaddr, *addr;
- address_item *last_first = NULL;
- address_item **paddr = i==0 ? addr_succeed :
- i==1 ? addr_failed : addr_defer;
- address_item **saved_paddr = NULL;
+ address_item * endaddr, *addr;
+ address_item * last_first = NULL;
+ address_item ** paddr = i==0 ? addr_succeed : i==1 ? addr_failed : addr_defer;
+ address_item ** saved_paddr = NULL;
DEBUG(D_retry) debug_printf("%s addresses:\n",
i == 0 ? "Succeeded" : i == 1 ? "Failed" : "Deferred");
}
/* End of retry.c */
+/* vi: aw ai sw=2
+*/