comparison src/mail/ngx_mail.c @ 290:f745bf973510 NGINX_0_5_15

nginx 0.5.15 *) Feature: the mail proxy supports authenticated SMTP proxying and the "smtp_auth", "smtp_capablities", and "xclient" directives. Thanks to Anton Yuzhaninov and Maxim Dounin. *) Feature: now the keep-alive connections are closed just after receiving the reconfiguration signal. *) Change: the "imap" and "auth" directives were renamed to the "mail" and "pop3_auth" directives. *) Bugfix: a segmentation fault occurred in worker process if the CRAM-MD5 authentication method was used and the APOP method was disabled. *) Bugfix: if the "starttls only" directive was used in POP3 protocol, then nginx allowed authentication without switching to the SSL mode. *) Bugfix: worker processes did not exit after reconfiguration and did not rotate logs if the eventport method was used. *) Bugfix: a worker process may got caught in an endless loop, if the "ip_hash" directive was used. *) Bugfix: now nginx does not log some alerts if eventport or /dev/poll methods are used.
author Igor Sysoev <http://sysoev.ru>
date Mon, 19 Mar 2007 00:00:00 +0300
parents
children 9b7db0df50f0
comparison
equal deleted inserted replaced
289:a9323c9433a7 290:f745bf973510
1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
10 #include <ngx_mail.h>
11
12
13 static char *ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
14 static int ngx_libc_cdecl ngx_mail_cmp_conf_in_addrs(const void *one,
15 const void *two);
16
17
18 ngx_uint_t ngx_mail_max_module;
19
20
21 static ngx_command_t ngx_mail_commands[] = {
22
23 { ngx_string("mail"),
24 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
25 ngx_mail_block,
26 0,
27 0,
28 NULL },
29
30 { ngx_string("imap"),
31 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
32 ngx_mail_block,
33 0,
34 0,
35 NULL },
36
37 ngx_null_command
38 };
39
40
41 static ngx_core_module_t ngx_mail_module_ctx = {
42 ngx_string("mail"),
43 NULL,
44 NULL
45 };
46
47
48 ngx_module_t ngx_mail_module = {
49 NGX_MODULE_V1,
50 &ngx_mail_module_ctx, /* module context */
51 ngx_mail_commands, /* module directives */
52 NGX_CORE_MODULE, /* module type */
53 NULL, /* init master */
54 NULL, /* init module */
55 NULL, /* init process */
56 NULL, /* init thread */
57 NULL, /* exit thread */
58 NULL, /* exit process */
59 NULL, /* exit master */
60 NGX_MODULE_V1_PADDING
61 };
62
63
64 static char *
65 ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
66 {
67 char *rv;
68 u_char *text;
69 size_t len;
70 ngx_uint_t i, a, l, m, mi, s, p, last, bind_all, done;
71 ngx_conf_t pcf;
72 ngx_array_t in_ports;
73 ngx_listening_t *ls;
74 ngx_mail_listen_t *imls;
75 ngx_mail_module_t *module;
76 ngx_mail_in_port_t *imip;
77 ngx_mail_conf_ctx_t *ctx;
78 ngx_mail_conf_in_port_t *in_port;
79 ngx_mail_conf_in_addr_t *in_addr;
80 ngx_mail_core_srv_conf_t **cscfp;
81 ngx_mail_core_main_conf_t *cmcf;
82
83 if (cmd->name.data[0] == 'i') {
84 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
85 "the \"imap\" directive is deprecated, "
86 "use the \"mail\" directive instead");
87 }
88
89 /* the main mail context */
90
91 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t));
92 if (ctx == NULL) {
93 return NGX_CONF_ERROR;
94 }
95
96 *(ngx_mail_conf_ctx_t **) conf = ctx;
97
98 /* count the number of the http modules and set up their indices */
99
100 ngx_mail_max_module = 0;
101 for (m = 0; ngx_modules[m]; m++) {
102 if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
103 continue;
104 }
105
106 ngx_modules[m]->ctx_index = ngx_mail_max_module++;
107 }
108
109
110 /* the mail main_conf context, it is the same in the all mail contexts */
111
112 ctx->main_conf = ngx_pcalloc(cf->pool,
113 sizeof(void *) * ngx_mail_max_module);
114 if (ctx->main_conf == NULL) {
115 return NGX_CONF_ERROR;
116 }
117
118
119 /*
120 * the mail null srv_conf context, it is used to merge
121 * the server{}s' srv_conf's
122 */
123
124 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module);
125 if (ctx->srv_conf == NULL) {
126 return NGX_CONF_ERROR;
127 }
128
129
130 /*
131 * create the main_conf's, the null srv_conf's, and the null loc_conf's
132 * of the all mail modules
133 */
134
135 for (m = 0; ngx_modules[m]; m++) {
136 if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
137 continue;
138 }
139
140 module = ngx_modules[m]->ctx;
141 mi = ngx_modules[m]->ctx_index;
142
143 if (module->create_main_conf) {
144 ctx->main_conf[mi] = module->create_main_conf(cf);
145 if (ctx->main_conf[mi] == NULL) {
146 return NGX_CONF_ERROR;
147 }
148 }
149
150 if (module->create_srv_conf) {
151 ctx->srv_conf[mi] = module->create_srv_conf(cf);
152 if (ctx->srv_conf[mi] == NULL) {
153 return NGX_CONF_ERROR;
154 }
155 }
156 }
157
158
159 /* parse inside the mail{} block */
160
161 pcf = *cf;
162 cf->ctx = ctx;
163
164 cf->module_type = NGX_MAIL_MODULE;
165 cf->cmd_type = NGX_MAIL_MAIN_CONF;
166 rv = ngx_conf_parse(cf, NULL);
167
168 if (rv != NGX_CONF_OK) {
169 *cf = pcf;
170 return rv;
171 }
172
173
174 /* init mail{} main_conf's, merge the server{}s' srv_conf's */
175
176 cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index];
177 cscfp = cmcf->servers.elts;
178
179 for (m = 0; ngx_modules[m]; m++) {
180 if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
181 continue;
182 }
183
184 module = ngx_modules[m]->ctx;
185 mi = ngx_modules[m]->ctx_index;
186
187 /* init mail{} main_conf's */
188
189 if (module->init_main_conf) {
190 rv = module->init_main_conf(cf, ctx->main_conf[mi]);
191 if (rv != NGX_CONF_OK) {
192 *cf = pcf;
193 return rv;
194 }
195 }
196
197 for (s = 0; s < cmcf->servers.nelts; s++) {
198
199 /* merge the server{}s' srv_conf's */
200
201 if (module->merge_srv_conf) {
202 rv = module->merge_srv_conf(cf,
203 ctx->srv_conf[mi],
204 cscfp[s]->ctx->srv_conf[mi]);
205 if (rv != NGX_CONF_OK) {
206 *cf = pcf;
207 return rv;
208 }
209 }
210 }
211 }
212
213 /* mail{}'s cf->ctx was needed while the configuration merging */
214
215 *cf = pcf;
216
217
218 if (ngx_array_init(&in_ports, cf->temp_pool, 4,
219 sizeof(ngx_mail_conf_in_port_t))
220 != NGX_OK)
221 {
222 return NGX_CONF_ERROR;
223 }
224
225 imls = cmcf->listen.elts;
226
227 for (l = 0; l < cmcf->listen.nelts; l++) {
228
229 /* AF_INET only */
230
231 in_port = in_ports.elts;
232 for (p = 0; p < in_ports.nelts; p++) {
233 if (in_port[p].port == imls[l].port) {
234 in_port = &in_port[p];
235 goto found;
236 }
237 }
238
239 in_port = ngx_array_push(&in_ports);
240 if (in_port == NULL) {
241 return NGX_CONF_ERROR;
242 }
243
244 in_port->port = imls[l].port;
245
246 if (ngx_array_init(&in_port->addrs, cf->temp_pool, 2,
247 sizeof(ngx_mail_conf_in_addr_t))
248 != NGX_OK)
249 {
250 return NGX_CONF_ERROR;
251 }
252
253 found:
254
255 in_addr = ngx_array_push(&in_port->addrs);
256 if (in_addr == NULL) {
257 return NGX_CONF_ERROR;
258 }
259
260 in_addr->addr = imls[l].addr;
261 in_addr->ctx = imls[l].ctx;
262 in_addr->bind = imls[l].bind;
263 }
264
265 /* optimize the lists of ports and addresses */
266
267 /* AF_INET only */
268
269 in_port = in_ports.elts;
270 for (p = 0; p < in_ports.nelts; p++) {
271
272 ngx_qsort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts,
273 sizeof(ngx_mail_conf_in_addr_t), ngx_mail_cmp_conf_in_addrs);
274
275 in_addr = in_port[p].addrs.elts;
276 last = in_port[p].addrs.nelts;
277
278 /*
279 * if there is the binding to the "*:port" then we need to bind()
280 * to the "*:port" only and ignore the other bindings
281 */
282
283 if (in_addr[last - 1].addr == INADDR_ANY) {
284 in_addr[last - 1].bind = 1;
285 bind_all = 0;
286
287 } else {
288 bind_all = 1;
289 }
290
291 for (a = 0; a < last; /* void */ ) {
292
293 if (!bind_all && !in_addr[a].bind) {
294 a++;
295 continue;
296 }
297
298 ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr,
299 in_port[p].port);
300 if (ls == NULL) {
301 return NGX_CONF_ERROR;
302 }
303
304 ls->backlog = -1;
305 ls->rcvbuf = -1;
306 ls->sndbuf = -1;
307
308 ls->addr_ntop = 1;
309 ls->handler = ngx_mail_init_connection;
310 ls->pool_size = 256;
311
312 /* STUB */
313 ls->log = *cf->cycle->new_log;
314 ls->log.data = &ls->addr_text;
315 ls->log.handler = ngx_accept_log_error;
316 /**/
317
318 imip = ngx_palloc(cf->pool, sizeof(ngx_mail_in_port_t));
319 if (imip == NULL) {
320 return NGX_CONF_ERROR;
321 }
322
323 ls->servers = imip;
324
325 in_addr = in_port[p].addrs.elts;
326
327 if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
328 imip->naddrs = 1;
329 done = 0;
330
331 } else if (in_port[p].addrs.nelts > 1
332 && in_addr[last - 1].addr == INADDR_ANY)
333 {
334 imip->naddrs = last;
335 done = 1;
336
337 } else {
338 imip->naddrs = 1;
339 done = 0;
340 }
341
342 #if 0
343 ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
344 "%ui: %V %d %ui %ui",
345 a, &ls->addr_text, in_addr[a].bind,
346 imip->naddrs, last);
347 #endif
348
349 imip->addrs = ngx_pcalloc(cf->pool,
350 imip->naddrs * sizeof(ngx_mail_in_addr_t));
351 if (imip->addrs == NULL) {
352 return NGX_CONF_ERROR;
353 }
354
355 for (i = 0; i < imip->naddrs; i++) {
356 imip->addrs[i].addr = in_addr[i].addr;
357 imip->addrs[i].ctx = in_addr[i].ctx;
358
359 text = ngx_palloc(cf->pool,
360 INET_ADDRSTRLEN - 1 + sizeof(":65535") - 1);
361 if (text == NULL) {
362 return NGX_CONF_ERROR;
363 }
364
365 len = ngx_inet_ntop(AF_INET, &in_addr[i].addr, text,
366 INET_ADDRSTRLEN);
367
368 len = ngx_sprintf(text + len, ":%d", in_port[p].port) - text;
369
370 imip->addrs[i].addr_text.len = len;
371 imip->addrs[i].addr_text.data = text;
372 }
373
374 if (done) {
375 break;
376 }
377
378 in_addr++;
379 in_port[p].addrs.elts = in_addr;
380 last--;
381
382 a = 0;
383 }
384 }
385
386 return NGX_CONF_OK;
387 }
388
389
390 static int ngx_libc_cdecl
391 ngx_mail_cmp_conf_in_addrs(const void *one, const void *two)
392 {
393 ngx_mail_conf_in_addr_t *first, *second;
394
395 first = (ngx_mail_conf_in_addr_t *) one;
396 second = (ngx_mail_conf_in_addr_t *) two;
397
398 if (first->addr == INADDR_ANY) {
399 /* the INADDR_ANY must be the last resort, shift it to the end */
400 return 1;
401 }
402
403 if (first->bind && !second->bind) {
404 /* shift explicit bind()ed addresses to the start */
405 return -1;
406 }
407
408 if (!first->bind && second->bind) {
409 /* shift explicit bind()ed addresses to the start */
410 return 1;
411 }
412
413 /* do not sort by default */
414
415 return 0;
416 }