~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/mail/ngx_mail.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.