1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
6 /* See the file NOTICE for conditions of use and distribution. */
10 #include "rf_functions.h"
11 #include "ipliteral.h"
14 /* Options specific to the ipliteral router. Because some compilers do not like
15 empty declarations ("undefined" in the Standard) we put in a dummy value. */
17 optionlist ipliteral_router_options[] = {
18 { "", opt_hidden, NULL }
21 /* Size of the options list. An extern variable has to be used so that its
22 address can appear in the tables drtables.c. */
24 int ipliteral_router_options_count =
25 sizeof(ipliteral_router_options)/sizeof(optionlist);
27 /* Default private options block for the ipliteral router. Again, a dummy
28 value is present to keep some compilers happy. */
30 ipliteral_router_options_block ipliteral_router_option_defaults = { 0 };
36 void ipliteral_router_init(router_instance *rblock) {}
37 int ipliteral_router_entry(router_instance *rblock, address_item *addr,
38 struct passwd *pw, int verify, address_item **addr_local,
39 address_item **addr_remote, address_item **addr_new,
40 address_item **addr_succeed) {return 0;}
42 #else /*!MACRO_PREDEF*/
45 /*************************************************
46 * Initialization entry point *
47 *************************************************/
49 /* Called for each instance, after its options have been read, to enable
50 consistency checks to be done, or anything else that needs to be set up. */
53 ipliteral_router_init(router_instance *rblock)
56 ipliteral_router_options_block *ob =
57 (ipliteral_router_options_block *)(rblock->options_block);
64 /*************************************************
66 *************************************************/
68 /* See local README for interface details. This router returns:
71 . the domain is not in the form of an IP literal
74 . verifying the errors address caused a deferment or a big disaster such
75 as an expansion failure (rf_get_errors_address)
76 . expanding a headers_{add,remove} string caused a deferment or another
77 expansion error (rf_get_munge_headers)
78 . a problem in rf_get_transport: no transport when one is needed;
79 failed to expand dynamic transport; failed to find dynamic transport
80 . failure to expand or find a uid/gid (rf_get_ugid via rf_queue_add)
81 . self = "freeze", self = "defer"
93 added address to addr_local or addr_remote, as appropriate for the
94 type of transport; this includes the self="send" case.
98 ipliteral_router_entry(
99 router_instance *rblock, /* data for this instantiation */
100 address_item *addr, /* address we are working on */
101 struct passwd *pw, /* passwd entry after check_local_user */
102 int verify, /* v_none/v_recipient/v_sender/v_expn */
103 address_item **addr_local, /* add it to this if it's local */
104 address_item **addr_remote, /* add it to this if it's remote */
105 address_item **addr_new, /* put new addresses on here */
106 address_item **addr_succeed) /* put old address here on success */
109 ipliteral_router_options_block *ob =
110 (ipliteral_router_options_block *)(rblock->options_block);
113 const uschar *domain = addr->domain;
115 int len = Ustrlen(domain);
118 addr_new = addr_new; /* Keep picky compilers happy */
119 addr_succeed = addr_succeed;
121 DEBUG(D_route) debug_printf("%s router called for %s: domain = %s\n",
122 rblock->name, addr->address, addr->domain);
124 /* Check that the domain is an IP address enclosed in square brackets. Remember
125 to allow for the "official" form of IPv6 addresses. If not, the router
126 declines. Otherwise route to the single IP address, setting the host name to
129 if (domain[0] != '[' || domain[len-1] != ']') return DECLINE;
130 ip = string_copyn(domain+1, len-2);
131 if (strncmpic(ip, US"IPV6:", 5) == 0 || strncmpic(ip, US"IPV4:", 5) == 0)
134 ipv = string_is_ip_address(ip, NULL);
135 if (ipv == 0 || (disable_ipv6 && ipv == 6))
138 /* It seems unlikely that ignore_target_hosts will be used with this router,
139 but if it is set, it should probably work. */
141 if (verify_check_this_host(CUSS&rblock->ignore_target_hosts,
142 NULL, domain, ip, NULL) == OK)
145 debug_printf("%s is in ignore_target_hosts\n", ip);
146 addr->message = US"IP literal host explicitly ignored";
150 /* Set up a host item */
152 h = store_get(sizeof(host_item), FALSE);
155 h->address = string_copy(ip);
159 h->status = hstatus_unknown;
160 h->why = hwhy_unknown;
163 /* Determine whether the host is the local host, and if so, take action
164 according to the configuration. */
166 if (host_scan_for_local_hosts(h, &h, NULL) == HOST_FOUND_LOCAL)
168 int rc = rf_self_action(addr, h, rblock->self_code, rblock->self_rewrite,
169 rblock->self, addr_new);
170 if (rc != OK) return rc;
173 /* Address is routed to this host */
177 /* Set up the errors address, if any. */
179 rc = rf_get_errors_address(addr, rblock, verify, &addr->prop.errors_address);
180 if (rc != OK) return rc;
182 /* Set up the additional and removable headers for this address. */
184 rc = rf_get_munge_headers(addr, rblock, &addr->prop.extra_headers,
185 &addr->prop.remove_headers);
186 if (rc != OK) return rc;
188 /* Fill in the transport, queue the address for local or remote delivery, and
189 yield success. For local delivery, of course, the IP address won't be used. If
190 just verifying, there need not be a transport, in which case it doesn't matter
191 which queue we put the address on. This is all now handled by the route_queue()
194 if (!rf_get_transport(rblock->transport_name, &(rblock->transport),
195 addr, rblock->name, NULL))
198 addr->transport = rblock->transport;
200 return rf_queue_add(addr, addr_local, addr_remote, rblock, pw)?
204 #endif /*!MACRO_PREDEF*/
205 /* End of routers/ipliteral.c */