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