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