ipliteral was not recognizing "ipv6" prefix.
[exim.git] / src / src / routers / ipliteral.c
1 /* $Cambridge: exim/src/src/routers/ipliteral.c,v 1.6 2005/12/05 14:38:18 ph10 Exp $ */
2
3 /*************************************************
4 *     Exim - an Internet mail transport agent    *
5 *************************************************/
6
7 /* Copyright (c) University of Cambridge 1995 - 2005 */
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
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
36 /*************************************************
37 *          Initialization entry point            *
38 *************************************************/
39
40 /* Called for each instance, after its options have been read, to enable
41 consistency checks to be done, or anything else that needs to be set up. */
42
43 void
44 ipliteral_router_init(router_instance *rblock)
45 {
46 /*
47 ipliteral_router_options_block *ob =
48   (ipliteral_router_options_block *)(rblock->options_block);
49 */
50 rblock = rblock;
51 }
52
53
54
55 /*************************************************
56 *              Main entry point                  *
57 *************************************************/
58
59 /* See local README for interface details. This router returns:
60
61 DECLINE
62   . the domain is not in the form of an IP literal
63
64 DEFER
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
74 PASS
75   . self = "pass"
76
77 REROUTED
78   . self = "reroute"
79
80 FAIL
81   . self = "fail"
82
83 OK
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
88 int
89 ipliteral_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 */
93   int verify,                     /* v_none/v_recipient/v_sender/v_expn */
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 /*
100 ipliteral_router_options_block *ob =
101   (ipliteral_router_options_block *)(rblock->options_block);
102 */
103 host_item *h;
104 uschar *domain = addr->domain;
105 uschar *ip;
106 int len = Ustrlen(domain);
107 int rc;
108
109 addr_new = addr_new;         /* Keep picky compilers happy */
110 addr_succeed = addr_succeed;
111
112 DEBUG(D_route) debug_printf("%s router called for %s: domain = %s\n",
113   rblock->name, addr->address, addr->domain);
114
115 /* Check that the domain is an IP address enclosed in square brackets. Remember
116 to allow for the "official" form of IPv6 addresses. If not, the router
117 declines. Otherwise route to the single IP address, setting the host name to
118 "(unnamed)". */
119
120 if (domain[0] != '[' || domain[len-1] != ']') return DECLINE;
121 domain[len-1] = 0;  /* temporarily */
122
123 ip = domain + 1;
124 if (strncmpic(ip, US"IPV6:", 5) == 0 || strncmpic(ip, US"IPV4:", 5) == 0)
125   ip += 5;
126
127 if (string_is_ip_address(ip, NULL) == 0)
128   {
129   domain[len-1] = ']';
130   return DECLINE;
131   }
132
133 /* It seems unlikely that ignore_target_hosts will be used with this router,
134 but if it is set, it should probably work. */
135
136 if (verify_check_this_host(&(rblock->ignore_target_hosts), NULL, domain,
137       ip, NULL) == OK)
138   {
139   DEBUG(D_route)
140       debug_printf("%s is in ignore_target_hosts\n", ip);
141   addr->message = US"IP literal host explicitly ignored";
142   domain[len-1] = ']';
143   return DECLINE;
144   }
145
146 /* Set up a host item */
147
148 h = store_get(sizeof(host_item));
149
150 h->next = NULL;
151 h->address = string_copy(ip);
152 h->port = PORT_NONE;
153 domain[len-1] = ']';   /* restore */
154 h->name = string_copy(domain);
155 h->mx = MX_NONE;
156 h->status = hstatus_unknown;
157 h->why = hwhy_unknown;
158 h->last_try = 0;
159
160 /* Determine whether the host is the local host, and if so, take action
161 according to the configuration. */
162
163 if (host_scan_for_local_hosts(h, &h, NULL) == HOST_FOUND_LOCAL)
164   {
165   int rc = rf_self_action(addr, h, rblock->self_code, rblock->self_rewrite,
166     rblock->self, addr_new);
167   if (rc != OK) return rc;
168   }
169
170 /* Address is routed to this host */
171
172 addr->host_list = h;
173
174 /* Set up the errors address, if any. */
175
176 rc = rf_get_errors_address(addr, rblock, verify, &(addr->p.errors_address));
177 if (rc != OK) return rc;
178
179 /* Set up the additional and removeable headers for this address. */
180
181 rc = rf_get_munge_headers(addr, rblock, &(addr->p.extra_headers),
182   &(addr->p.remove_headers));
183 if (rc != OK) return rc;
184
185 /* Fill in the transport, queue the address for local or remote delivery, and
186 yield success. For local delivery, of course, the IP address won't be used. If
187 just verifying, there need not be a transport, in which case it doesn't matter
188 which queue we put the address on. This is all now handled by the route_queue()
189 function. */
190
191 if (!rf_get_transport(rblock->transport_name, &(rblock->transport),
192       addr, rblock->name, NULL))
193   return DEFER;
194
195 addr->transport = rblock->transport;
196
197 return rf_queue_add(addr, addr_local, addr_remote, rblock, pw)?
198   OK : DEFER;
199 }
200
201 /* End of routers/ipliteral.c */