Copyright updates:
[exim.git] / src / src / routers / ipliteral.c
CommitLineData
0756eb3c
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
f9ba5e22 5/* Copyright (c) University of Cambridge 1995 - 2018 */
1e1ddfac 6/* Copyright (c) The Exim Maintainers 2020 */
0756eb3c
PH
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
16empty declarations ("undefined" in the Standard) we put in a dummy value. */
17
18optionlist ipliteral_router_options[] = {
23f2e90d 19 { "", opt_hidden, {NULL} }
0756eb3c
PH
20};
21
22/* Size of the options list. An extern variable has to be used so that its
23address can appear in the tables drtables.c. */
24
25int ipliteral_router_options_count =
26 sizeof(ipliteral_router_options)/sizeof(optionlist);
27
28/* Default private options block for the ipliteral router. Again, a dummy
29value is present to keep some compilers happy. */
30
31ipliteral_router_options_block ipliteral_router_option_defaults = { 0 };
32
33
d185889f
JH
34#ifdef MACRO_PREDEF
35
36/* Dummy entries */
37void ipliteral_router_init(router_instance *rblock) {}
38int 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,
cab0c277 41 address_item **addr_succeed) {return 0;}
d185889f
JH
42
43#else /*!MACRO_PREDEF*/
44
0756eb3c
PH
45
46/*************************************************
47* Initialization entry point *
48*************************************************/
49
50/* Called for each instance, after its options have been read, to enable
51consistency checks to be done, or anything else that needs to be set up. */
52
53void
54ipliteral_router_init(router_instance *rblock)
55{
56/*
57ipliteral_router_options_block *ob =
58 (ipliteral_router_options_block *)(rblock->options_block);
59*/
60rblock = rblock;
61}
62
63
64
65/*************************************************
66* Main entry point *
67*************************************************/
68
69/* See local README for interface details. This router returns:
70
71DECLINE
72 . the domain is not in the form of an IP literal
73
74DEFER
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
84PASS
85 . self = "pass"
86
87REROUTED
88 . self = "reroute"
89
90FAIL
91 . self = "fail"
92
93OK
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
98int
99ipliteral_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 */
fd6de02e 103 int verify, /* v_none/v_recipient/v_sender/v_expn */
0756eb3c
PH
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/*
110ipliteral_router_options_block *ob =
111 (ipliteral_router_options_block *)(rblock->options_block);
112*/
113host_item *h;
55414b25
JH
114const uschar *domain = addr->domain;
115const uschar *ip;
0756eb3c 116int len = Ustrlen(domain);
7e66e54d 117int rc, ipv;
0756eb3c
PH
118
119addr_new = addr_new; /* Keep picky compilers happy */
120addr_succeed = addr_succeed;
121
122DEBUG(D_route) debug_printf("%s router called for %s: domain = %s\n",
123 rblock->name, addr->address, addr->domain);
124
f9daeae0
PH
125/* Check that the domain is an IP address enclosed in square brackets. Remember
126to allow for the "official" form of IPv6 addresses. If not, the router
127declines. Otherwise route to the single IP address, setting the host name to
128"(unnamed)". */
0756eb3c
PH
129
130if (domain[0] != '[' || domain[len-1] != ']') return DECLINE;
55414b25 131ip = string_copyn(domain+1, len-2);
f9daeae0
PH
132if (strncmpic(ip, US"IPV6:", 5) == 0 || strncmpic(ip, US"IPV4:", 5) == 0)
133 ip += 5;
134
7e66e54d
PH
135ipv = string_is_ip_address(ip, NULL);
136if (ipv == 0 || (disable_ipv6 && ipv == 6))
0756eb3c 137 return DECLINE;
0756eb3c
PH
138
139/* It seems unlikely that ignore_target_hosts will be used with this router,
140but if it is set, it should probably work. */
141
55414b25
JH
142if (verify_check_this_host(CUSS&rblock->ignore_target_hosts,
143 NULL, domain, ip, NULL) == OK)
0756eb3c
PH
144 {
145 DEBUG(D_route)
f9daeae0 146 debug_printf("%s is in ignore_target_hosts\n", ip);
0756eb3c 147 addr->message = US"IP literal host explicitly ignored";
0756eb3c
PH
148 return DECLINE;
149 }
150
151/* Set up a host item */
152
f3ebb786 153h = store_get(sizeof(host_item), FALSE);
0756eb3c
PH
154
155h->next = NULL;
f9daeae0 156h->address = string_copy(ip);
0756eb3c 157h->port = PORT_NONE;
55414b25 158h->name = domain;
0756eb3c
PH
159h->mx = MX_NONE;
160h->status = hstatus_unknown;
161h->why = hwhy_unknown;
162h->last_try = 0;
163
164/* Determine whether the host is the local host, and if so, take action
165according to the configuration. */
166
167if (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
176addr->host_list = h;
177
178/* Set up the errors address, if any. */
179
d43cbe25 180rc = rf_get_errors_address(addr, rblock, verify, &addr->prop.errors_address);
0756eb3c
PH
181if (rc != OK) return rc;
182
aded2255 183/* Set up the additional and removable headers for this address. */
0756eb3c 184
d43cbe25
JH
185rc = rf_get_munge_headers(addr, rblock, &addr->prop.extra_headers,
186 &addr->prop.remove_headers);
0756eb3c
PH
187if (rc != OK) return rc;
188
189/* Fill in the transport, queue the address for local or remote delivery, and
190yield success. For local delivery, of course, the IP address won't be used. If
191just verifying, there need not be a transport, in which case it doesn't matter
192which queue we put the address on. This is all now handled by the route_queue()
193function. */
194
195if (!rf_get_transport(rblock->transport_name, &(rblock->transport),
196 addr, rblock->name, NULL))
197 return DEFER;
198
199addr->transport = rblock->transport;
200
201return rf_queue_add(addr, addr_local, addr_remote, rblock, pw)?
202 OK : DEFER;
203}
204
d185889f 205#endif /*!MACRO_PREDEF*/
0756eb3c 206/* End of routers/ipliteral.c */