SPDX: Mass-update to GPL-2.0-or-later
[exim.git] / src / src / routers / ipliteral.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
9
10
11 #include "../exim.h"
12 #include "rf_functions.h"
13 #include "ipliteral.h"
14
15
16 /* Options specific to the ipliteral router. Because some compilers do not like
17 empty declarations ("undefined" in the Standard) we put in a dummy value. */
18
19 optionlist ipliteral_router_options[] = {
20   { "", opt_hidden, {NULL} }
21 };
22
23 /* Size of the options list. An extern variable has to be used so that its
24 address can appear in the tables drtables.c. */
25
26 int ipliteral_router_options_count =
27   sizeof(ipliteral_router_options)/sizeof(optionlist);
28
29 /* Default private options block for the ipliteral router. Again, a dummy
30 value is present to keep some compilers happy. */
31
32 ipliteral_router_options_block ipliteral_router_option_defaults = { 0 };
33
34
35 #ifdef MACRO_PREDEF
36
37 /* Dummy entries */
38 void ipliteral_router_init(router_instance *rblock) {}
39 int ipliteral_router_entry(router_instance *rblock, address_item *addr,
40   struct passwd *pw, int verify, address_item **addr_local,
41   address_item **addr_remote, address_item **addr_new,
42   address_item **addr_succeed) {return 0;}
43
44 #else   /*!MACRO_PREDEF*/
45
46
47 /*************************************************
48 *          Initialization entry point            *
49 *************************************************/
50
51 /* Called for each instance, after its options have been read, to enable
52 consistency checks to be done, or anything else that needs to be set up. */
53
54 void
55 ipliteral_router_init(router_instance *rblock)
56 {
57 /*
58 ipliteral_router_options_block *ob =
59   (ipliteral_router_options_block *)(rblock->options_block);
60 */
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 DEBUG(D_route) debug_printf("%s router called for %s: domain = %s\n",
120   rblock->name, addr->address, addr->domain);
121
122 /* Check that the domain is an IP address enclosed in square brackets. Remember
123 to allow for the "official" form of IPv6 addresses. If not, the router
124 declines. Otherwise route to the single IP address, setting the host name to
125 "(unnamed)". */
126
127 if (domain[0] != '[' || domain[len-1] != ']') return DECLINE;
128 ip = string_copyn(domain+1, len-2);
129 if (strncmpic(ip, US"IPV6:", 5) == 0 || strncmpic(ip, US"IPV4:", 5) == 0)
130   ip += 5;
131
132 ipv = string_is_ip_address(ip, NULL);
133 if (ipv == 0 || (disable_ipv6 && ipv == 6))
134   return DECLINE;
135
136 /* It seems unlikely that ignore_target_hosts will be used with this router,
137 but if it is set, it should probably work. */
138
139 if (verify_check_this_host(CUSS&rblock->ignore_target_hosts,
140         NULL, domain, ip, NULL) == OK)
141   {
142   DEBUG(D_route)
143       debug_printf("%s is in ignore_target_hosts\n", ip);
144   addr->message = US"IP literal host explicitly ignored";
145   return DECLINE;
146   }
147
148 /* Set up a host item */
149
150 h = store_get(sizeof(host_item), GET_UNTAINTED);
151
152 h->next = NULL;
153 h->address = string_copy(ip);
154 h->port = PORT_NONE;
155 h->name = domain;
156 h->mx = MX_NONE;
157 h->status = hstatus_unknown;
158 h->why = hwhy_unknown;
159 h->last_try = 0;
160
161 /* Determine whether the host is the local host, and if so, take action
162 according to the configuration. */
163
164 if (host_scan_for_local_hosts(h, &h, NULL) == HOST_FOUND_LOCAL)
165   {
166   int rc = rf_self_action(addr, h, rblock->self_code, rblock->self_rewrite,
167     rblock->self, addr_new);
168   if (rc != OK) return rc;
169   }
170
171 /* Address is routed to this host */
172
173 addr->host_list = h;
174
175 /* Set up the errors address, if any. */
176
177 rc = rf_get_errors_address(addr, rblock, verify, &addr->prop.errors_address);
178 if (rc != OK) return rc;
179
180 /* Set up the additional and removable headers for this address. */
181
182 rc = rf_get_munge_headers(addr, rblock, &addr->prop.extra_headers,
183   &addr->prop.remove_headers);
184 if (rc != OK) return rc;
185
186 /* Fill in the transport, queue the address for local or remote delivery, and
187 yield success. For local delivery, of course, the IP address won't be used. If
188 just verifying, there need not be a transport, in which case it doesn't matter
189 which queue we put the address on. This is all now handled by the route_queue()
190 function. */
191
192 if (!rf_get_transport(rblock->transport_name, &(rblock->transport),
193       addr, rblock->name, NULL))
194   return DEFER;
195
196 addr->transport = rblock->transport;
197
198 return rf_queue_add(addr, addr_local, addr_remote, rblock, pw)?
199   OK : DEFER;
200 }
201
202 #endif   /*!MACRO_PREDEF*/
203 /* End of routers/ipliteral.c */