* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) The Exim Maintainers 2020 - 2022 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
optionlist iplookup_router_options[] = {
{ "hosts", opt_stringptr,
- (void *)(offsetof(iplookup_router_options_block, hosts)) },
+ OPT_OFF(iplookup_router_options_block, hosts) },
{ "optional", opt_bool,
- (void *)(offsetof(iplookup_router_options_block, optional)) },
+ OPT_OFF(iplookup_router_options_block, optional) },
{ "port", opt_int,
- (void *)(offsetof(iplookup_router_options_block, port)) },
+ OPT_OFF(iplookup_router_options_block, port) },
{ "protocol", opt_stringptr,
- (void *)(offsetof(iplookup_router_options_block, protocol_name)) },
+ OPT_OFF(iplookup_router_options_block, protocol_name) },
{ "query", opt_stringptr,
- (void *)(offsetof(iplookup_router_options_block, query)) },
+ OPT_OFF(iplookup_router_options_block, query) },
{ "reroute", opt_stringptr,
- (void *)(offsetof(iplookup_router_options_block, reroute)) },
+ OPT_OFF(iplookup_router_options_block, reroute) },
{ "response_pattern", opt_stringptr,
- (void *)(offsetof(iplookup_router_options_block, response_pattern)) },
+ OPT_OFF(iplookup_router_options_block, response_pattern) },
{ "timeout", opt_time,
- (void *)(offsetof(iplookup_router_options_block, timeout)) }
+ OPT_OFF(iplookup_router_options_block, timeout) }
};
/* Size of the options list. An extern variable has to be used so that its
int iplookup_router_entry(router_instance *rblock, address_item *addr,
struct passwd *pw, int verify, address_item **addr_local,
address_item **addr_remote, address_item **addr_new,
- address_item **addr_succeed) {}
+ address_item **addr_succeed) {return 0;}
#else /*!MACRO_PREDEF*/
consistency checks to be done, or anything else that needs to be set up. */
void
-iplookup_router_init(router_instance *rblock)
+iplookup_router_init(router_instance * rblock)
{
-iplookup_router_options_block *ob =
- (iplookup_router_options_block *)(rblock->options_block);
+iplookup_router_options_block * ob =
+ (iplookup_router_options_block *) rblock->options_block;
/* A port and a host list must be given */
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n "
"a port must be specified", rblock->name);
-if (ob->hosts == NULL)
+if (!ob->hosts)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n "
"a host list must be specified", rblock->name);
/* Translate protocol name into value */
-if (ob->protocol_name != NULL)
+if (ob->protocol_name)
{
if (Ustrcmp(ob->protocol_name, "udp") == 0) ob->protocol = ip_udp;
else if (Ustrcmp(ob->protocol_name, "tcp") == 0) ob->protocol = ip_tcp;
/* If a response pattern is given, compile it now to get the error early. */
-if (ob->response_pattern != NULL)
+if (ob->response_pattern)
ob->re_response_pattern =
- regex_must_compile(ob->response_pattern, FALSE, TRUE);
+ regex_must_compile(ob->response_pattern, MCS_NOFLAGS, TRUE);
}
uschar *hostname, *reroute, *domain;
const uschar *listptr;
uschar host_buffer[256];
-host_item *host = store_get(sizeof(host_item));
+host_item *host = store_get(sizeof(host_item), GET_UNTAINTED);
address_item *new_addr;
iplookup_router_options_block *ob =
(iplookup_router_options_block *)(rblock->options_block);
-const pcre *re = ob->re_response_pattern;
+const pcre2_code *re = ob->re_response_pattern;
int count, query_len, rc;
int sep = 0;
-addr_local = addr_local; /* Keep picky compilers happy */
-addr_remote = addr_remote;
-addr_succeed = addr_succeed;
-pw = pw;
-
DEBUG(D_route) debug_printf("%s router called for %s: domain = %s\n",
rblock->name, addr->address, addr->domain);
-reply = store_get(256);
+reply = store_get(256, GET_TAINTED);
/* Build the query string to send. If not explicitly given, a default of
"user@domain user@domain" is used. */
being a host list. */
listptr = ob->hosts;
+/* not expanded so should never be tainted */
while ((hostname = string_nextinlist(&listptr, &sep, host_buffer,
sizeof(host_buffer))))
{
for (h = host; h; h = h->next)
{
- int host_af, query_socket;
+ int host_af;
+ client_conn_ctx query_cctx = {0};
/* Skip any hosts for which we have no address */
host_af = (Ustrchr(h->address, ':') != NULL)? AF_INET6 : AF_INET;
- query_socket = ip_socket(ob->protocol == ip_udp ? SOCK_DGRAM:SOCK_STREAM,
+ query_cctx.sock = ip_socket(ob->protocol == ip_udp ? SOCK_DGRAM:SOCK_STREAM,
host_af);
- if (query_socket < 0)
+ if (query_cctx.sock < 0)
{
if (ob->optional) return PASS;
addr->message = string_sprintf("failed to create socket in %s router",
/* Connect to the remote host, under a timeout. In fact, timeouts can occur
here only for TCP calls; for a UDP socket, "connect" always works (the
router will timeout later on the read call). */
+/*XXX could take advantage of TFO */
- if (ip_connect(query_socket, host_af, h->address,ob->port, ob->timeout,
- ob->protocol != ip_udp) < 0)
+ if (ip_connect(query_cctx.sock, host_af, h->address,ob->port, ob->timeout,
+ ob->protocol == ip_udp ? NULL : &tcp_fastopen_nodata) < 0)
{
- close(query_socket);
+ close(query_cctx.sock);
DEBUG(D_route)
debug_printf("connection to %s failed: %s\n", h->address,
strerror(errno));
/* Send the query. If it fails, just continue with the next address. */
- if (send(query_socket, query, query_len, 0) < 0)
+ if (send(query_cctx.sock, query, query_len, 0) < 0)
{
DEBUG(D_route) debug_printf("send to %s failed\n", h->address);
- (void)close(query_socket);
+ (void)close(query_cctx.sock);
continue;
}
/* Read the response and close the socket. If the read fails, try the
next IP address. */
- count = ip_recv(query_socket, reply, sizeof(reply) - 1, ob->timeout);
- (void)close(query_socket);
+ count = ip_recv(&query_cctx, reply, sizeof(reply) - 1, time(NULL) + ob->timeout);
+ (void)close(query_cctx.sock);
if (count <= 0)
{
DEBUG(D_route) debug_printf("%s from %s\n", (errno == ETIMEDOUT)?
new_addr = deliver_make_addr(reroute, TRUE);
new_addr->parent = addr;
-copyflag(new_addr, addr, af_propagate);
new_addr->prop = addr->prop;
if (addr->child_count == USHRT_MAX)
new_addr->next = *addr_new;
*addr_new = new_addr;
-/* Set up the errors address, if any, and the additional and removeable headers
+/* Set up the errors address, if any, and the additional and removable headers
for this new address. */
rc = rf_get_errors_address(addr, rblock, verify, &new_addr->prop.errors_address);