Copyright updates:
[exim.git] / src / src / routers / iplookup.c
index 310e4d66d48f8585462c40bbb17668e0667478bd..02b43ee91431a35b153f982f2dbd5e308a95f429 100644 (file)
@@ -2,7 +2,8 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
 /* 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
@@ -44,6 +45,20 @@ address can appear in the tables drtables.c. */
 int iplookup_router_options_count =
   sizeof(iplookup_router_options)/sizeof(optionlist);
 
+
+#ifdef MACRO_PREDEF
+
+/* Dummy entries */
+iplookup_router_options_block iplookup_router_option_defaults = {0};
+void iplookup_router_init(router_instance *rblock) {}
+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) {return 0;}
+
+#else   /*!MACRO_PREDEF*/
+
+
 /* Default private options block for the iplookup router. */
 
 iplookup_router_options_block iplookup_router_option_defaults = {
@@ -146,7 +161,7 @@ uschar *reply;
 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), FALSE);
 address_item *new_addr;
 iplookup_router_options_block *ob =
   (iplookup_router_options_block *)(rblock->options_block);
@@ -162,7 +177,7 @@ 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, TRUE);  /* tainted data */
 
 /* Build the query string to send. If not explicitly given, a default of
 "user@domain user@domain" is used. */
@@ -191,7 +206,7 @@ being a host list. */
 
 listptr = ob->hosts;
 while ((hostname = string_nextinlist(&listptr, &sep, host_buffer,
-       sizeof(host_buffer))) != NULL)
+       sizeof(host_buffer))))
   {
   host_item *h;
 
@@ -214,21 +229,23 @@ while ((hostname = string_nextinlist(&listptr, &sep, host_buffer,
 
   /* Loop for possible multiple IP addresses for the given name. */
 
-  for (h = host; h != NULL; h = h->next)
+  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 */
 
-    if (h->address == NULL) continue;
+    if (!h->address) continue;
 
     /* Create a socket, for UDP or TCP, as configured. IPv6 addresses are
     detected by checking for a colon in the 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",
@@ -239,10 +256,12 @@ while ((hostname = string_nextinlist(&listptr, &sep, host_buffer,
     /* 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) < 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));
@@ -251,18 +270,18 @@ while ((hostname = string_nextinlist(&listptr, &sep, host_buffer,
 
     /* 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)?
@@ -282,7 +301,7 @@ while ((hostname = string_nextinlist(&listptr, &sep, host_buffer,
   /* If h == NULL we have tried all the IP addresses and failed on all of them,
   so we must continue to try more host names. Otherwise we have succeeded. */
 
-  if (h != NULL) break;
+  if (h) break;
   }
 
 
@@ -377,17 +396,16 @@ the chain of new addressess. */
 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 == SHRT_MAX)
+if (addr->child_count == USHRT_MAX)
   log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s router generated more than %d "
-    "child addresses for <%s>", rblock->name, SHRT_MAX, addr->address);
+    "child addresses for <%s>", rblock->name, USHRT_MAX, addr->address);
 addr->child_count++;
 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);
@@ -400,4 +418,5 @@ if (rc != OK) return rc;
 return OK;
 }
 
+#endif   /*!MACRO_PREDEF*/
 /* End of routers/iplookup.c */