debian experimental exim-daemon-heavy config
[exim.git] / src / src / routers / ipliteral.c
1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
6 /* Copyright (c) The Exim Maintainers 2020 */
7 /* See the file NOTICE for conditions of use and distribution. */
8
9
10 #include "../exim.h"
11 #include "rf_functions.h"
12 #include "ipliteral.h"
13
14
15 /* Options specific to the ipliteral router. Because some compilers do not like
16 empty declarations ("undefined" in the Standard) we put in a dummy value. */
17
18 optionlist ipliteral_router_options[] = {
19 { "", opt_hidden, {NULL} }
20 };
21
22 /* Size of the options list. An extern variable has to be used so that its
23 address can appear in the tables drtables.c. */
24
25 int ipliteral_router_options_count =
26 sizeof(ipliteral_router_options)/sizeof(optionlist);
27
28 /* Default private options block for the ipliteral router. Again, a dummy
29 value is present to keep some compilers happy. */
30
31 ipliteral_router_options_block ipliteral_router_option_defaults = { 0 };
32
33
34 #ifdef MACRO_PREDEF
35
36 /* Dummy entries */
37 void ipliteral_router_init(router_instance *rblock) {}
38 int ipliteral_router_entry(router_instance *rblock, address_item *addr,
39 struct passwd *pw, int verify, address_item **addr_local,
40 address_item **addr_remote, address_item **addr_new,
41 address_item **addr_succeed) {return 0;}
42
43 #else /*!MACRO_PREDEF*/
44
45
46 /*************************************************
47 * Initialization entry point *
48 *************************************************/
49
50 /* Called for each instance, after its options have been read, to enable
51 consistency checks to be done, or anything else that needs to be set up. */
52
53 void
54 ipliteral_router_init(router_instance *rblock)
55 {
56 /*
57 ipliteral_router_options_block *ob =
58 (ipliteral_router_options_block *)(rblock->options_block);
59 */
60 rblock = rblock;
61 }
62
63
64
65 /*************************************************
66 * Main entry point *
67 *************************************************/
68
69 /* See local README for interface details. This router returns:
70
71 DECLINE
72 . the domain is not in the form of an IP literal
73
74 DEFER
75 . verifying the errors address caused a deferment or a big disaster such
76 as an expansion failure (rf_get_errors_address)
77 . expanding a headers_{add,remove} string caused a deferment or another
78 expansion error (rf_get_munge_headers)
79 . a problem in rf_get_transport: no transport when one is needed;
80 failed to expand dynamic transport; failed to find dynamic transport
81 . failure to expand or find a uid/gid (rf_get_ugid via rf_queue_add)
82 . self = "freeze", self = "defer"
83
84 PASS
85 . self = "pass"
86
87 REROUTED
88 . self = "reroute"
89
90 FAIL
91 . self = "fail"
92
93 OK
94 added address to addr_local or addr_remote, as appropriate for the
95 type of transport; this includes the self="send" case.
96 */
97
98 int
99 ipliteral_router_entry(
100 router_instance *rblock, /* data for this instantiation */
101 address_item *addr, /* address we are working on */
102 struct passwd *pw, /* passwd entry after check_local_user */
103 int verify, /* v_none/v_recipient/v_sender/v_expn */
104 address_item **addr_local, /* add it to this if it's local */
105 address_item **addr_remote, /* add it to this if it's remote */
106 address_item **addr_new, /* put new addresses on here */
107 address_item **addr_succeed) /* put old address here on success */
108 {
109 /*
110 ipliteral_router_options_block *ob =
111 (ipliteral_router_options_block *)(rblock->options_block);
112 */
113 host_item *h;
114 const uschar *domain = addr->domain;
115 const uschar *ip;
116 int len = Ustrlen(domain);
117 int rc, ipv;
118
119 addr_new = addr_new; /* Keep picky compilers happy */
120 addr_succeed = addr_succeed;
121
122 DEBUG(D_route) debug_printf("%s router called for %s: domain = %s\n",
123 rblock->name, addr->address, addr->domain);
124
125 /* Check that the domain is an IP address enclosed in square brackets. Remember
126 to allow for the "official" form of IPv6 addresses. If not, the router
127 declines. Otherwise route to the single IP address, setting the host name to
128 "(unnamed)". */
129
130 if (domain[0] != '[' || domain[len-1] != ']') return DECLINE;
131 ip = string_copyn(domain+1, len-2);
132 if (strncmpic(ip, US"IPV6:", 5) == 0 || strncmpic(ip, US"IPV4:", 5) == 0)
133 ip += 5;
134
135 ipv = string_is_ip_address(ip, NULL);
136 if (ipv == 0 || (disable_ipv6 && ipv == 6))
137 return DECLINE;
138
139 /* It seems unlikely that ignore_target_hosts will be used with this router,
140 but if it is set, it should probably work. */
141
142 if (verify_check_this_host(CUSS&rblock->ignore_target_hosts,
143 NULL, domain, ip, NULL) == OK)
144 {
145 DEBUG(D_route)
146 debug_printf("%s is in ignore_target_hosts\n", ip);
147 addr->message = US"IP literal host explicitly ignored";
148 return DECLINE;
149 }
150
151 /* Set up a host item */
152
153 h = store_get(sizeof(host_item), FALSE);
154
155 h->next = NULL;
156 h->address = string_copy(ip);
157 h->port = PORT_NONE;
158 h->name = domain;
159 h->mx = MX_NONE;
160 h->status = hstatus_unknown;
161 h->why = hwhy_unknown;
162 h->last_try = 0;
163
164 /* Determine whether the host is the local host, and if so, take action
165 according to the configuration. */
166
167 if (host_scan_for_local_hosts(h, &h, NULL) == HOST_FOUND_LOCAL)
168 {
169 int rc = rf_self_action(addr, h, rblock->self_code, rblock->self_rewrite,
170 rblock->self, addr_new);
171 if (rc != OK) return rc;
172 }
173
174 /* Address is routed to this host */
175
176 addr->host_list = h;
177
178 /* Set up the errors address, if any. */
179
180 rc = rf_get_errors_address(addr, rblock, verify, &addr->prop.errors_address);
181 if (rc != OK) return rc;
182
183 /* Set up the additional and removable headers for this address. */
184
185 rc = rf_get_munge_headers(addr, rblock, &addr->prop.extra_headers,
186 &addr->prop.remove_headers);
187 if (rc != OK) return rc;
188
189 /* Fill in the transport, queue the address for local or remote delivery, and
190 yield success. For local delivery, of course, the IP address won't be used. If
191 just verifying, there need not be a transport, in which case it doesn't matter
192 which queue we put the address on. This is all now handled by the route_queue()
193 function. */
194
195 if (!rf_get_transport(rblock->transport_name, &(rblock->transport),
196 addr, rblock->name, NULL))
197 return DEFER;
198
199 addr->transport = rblock->transport;
200
201 return rf_queue_add(addr, addr_local, addr_remote, rblock, pw)?
202 OK : DEFER;
203 }
204
205 #endif /*!MACRO_PREDEF*/
206 /* End of routers/ipliteral.c */