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