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

Linux Cross Reference
Nginx/mail/ngx_mail.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

  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 ngx_int_t ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
 15     ngx_mail_listen_t *listen);
 16 static char *ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports);
 17 static ngx_int_t ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
 18     ngx_mail_conf_addr_t *addr);
 19 #if (NGX_HAVE_INET6)
 20 static ngx_int_t ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport,
 21     ngx_mail_conf_addr_t *addr);
 22 #endif
 23 static ngx_int_t ngx_mail_cmp_conf_addrs(const void *one, const void *two);
 24 
 25 
 26 ngx_uint_t  ngx_mail_max_module;
 27 
 28 
 29 static ngx_command_t  ngx_mail_commands[] = {
 30 
 31     { ngx_string("mail"),
 32       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
 33       ngx_mail_block,
 34       0,
 35       0,
 36       NULL },
 37 
 38     { ngx_string("imap"),
 39       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
 40       ngx_mail_block,
 41       0,
 42       0,
 43       NULL },
 44 
 45       ngx_null_command
 46 };
 47 
 48 
 49 static ngx_core_module_t  ngx_mail_module_ctx = {
 50     ngx_string("mail"),
 51     NULL,
 52     NULL
 53 };
 54 
 55 
 56 ngx_module_t  ngx_mail_module = {
 57     NGX_MODULE_V1,
 58     &ngx_mail_module_ctx,                  /* module context */
 59     ngx_mail_commands,                     /* module directives */
 60     NGX_CORE_MODULE,                       /* module type */
 61     NULL,                                  /* init master */
 62     NULL,                                  /* init module */
 63     NULL,                                  /* init process */
 64     NULL,                                  /* init thread */
 65     NULL,                                  /* exit thread */
 66     NULL,                                  /* exit process */
 67     NULL,                                  /* exit master */
 68     NGX_MODULE_V1_PADDING
 69 };
 70 
 71 
 72 static char *
 73 ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 74 {
 75     char                        *rv;
 76     ngx_uint_t                   i, m, mi, s;
 77     ngx_conf_t                   pcf;
 78     ngx_array_t                  ports;
 79     ngx_mail_listen_t           *listen;
 80     ngx_mail_module_t           *module;
 81     ngx_mail_conf_ctx_t         *ctx;
 82     ngx_mail_core_srv_conf_t   **cscfp;
 83     ngx_mail_core_main_conf_t   *cmcf;
 84 
 85     if (cmd->name.data[0] == 'i') {
 86         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
 87                            "the \"imap\" directive is deprecated, "
 88                            "use the \"mail\" directive instead");
 89     }
 90 
 91     /* the main mail context */
 92 
 93     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t));
 94     if (ctx == NULL) {
 95         return NGX_CONF_ERROR;
 96     }
 97 
 98     *(ngx_mail_conf_ctx_t **) conf = ctx;
 99 
100     /* count the number of the http modules and set up their indices */
101 
102     ngx_mail_max_module = 0;
103     for (m = 0; ngx_modules[m]; m++) {
104         if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
105             continue;
106         }
107 
108         ngx_modules[m]->ctx_index = ngx_mail_max_module++;
109     }
110 
111 
112     /* the mail main_conf context, it is the same in the all mail contexts */
113 
114     ctx->main_conf = ngx_pcalloc(cf->pool,
115                                  sizeof(void *) * ngx_mail_max_module);
116     if (ctx->main_conf == NULL) {
117         return NGX_CONF_ERROR;
118     }
119 
120 
121     /*
122      * the mail null srv_conf context, it is used to merge
123      * the server{}s' srv_conf's
124      */
125 
126     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module);
127     if (ctx->srv_conf == NULL) {
128         return NGX_CONF_ERROR;
129     }
130 
131 
132     /*
133      * create the main_conf's, the null srv_conf's, and the null loc_conf's
134      * of the all mail modules
135      */
136 
137     for (m = 0; ngx_modules[m]; m++) {
138         if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
139             continue;
140         }
141 
142         module = ngx_modules[m]->ctx;
143         mi = ngx_modules[m]->ctx_index;
144 
145         if (module->create_main_conf) {
146             ctx->main_conf[mi] = module->create_main_conf(cf);
147             if (ctx->main_conf[mi] == NULL) {
148                 return NGX_CONF_ERROR;
149             }
150         }
151 
152         if (module->create_srv_conf) {
153             ctx->srv_conf[mi] = module->create_srv_conf(cf);
154             if (ctx->srv_conf[mi] == NULL) {
155                 return NGX_CONF_ERROR;
156             }
157         }
158     }
159 
160 
161     /* parse inside the mail{} block */
162 
163     pcf = *cf;
164     cf->ctx = ctx;
165 
166     cf->module_type = NGX_MAIL_MODULE;
167     cf->cmd_type = NGX_MAIL_MAIN_CONF;
168     rv = ngx_conf_parse(cf, NULL);
169 
170     if (rv != NGX_CONF_OK) {
171         *cf = pcf;
172         return rv;
173     }
174 
175 
176     /* init mail{} main_conf's, merge the server{}s' srv_conf's */
177 
178     cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index];
179     cscfp = cmcf->servers.elts;
180 
181     for (m = 0; ngx_modules[m]; m++) {
182         if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
183             continue;
184         }
185 
186         module = ngx_modules[m]->ctx;
187         mi = ngx_modules[m]->ctx_index;
188 
189         /* init mail{} main_conf's */
190 
191         cf->ctx = ctx;
192 
193         if (module->init_main_conf) {
194             rv = module->init_main_conf(cf, ctx->main_conf[mi]);
195             if (rv != NGX_CONF_OK) {
196                 *cf = pcf;
197                 return rv;
198             }
199         }
200 
201         for (s = 0; s < cmcf->servers.nelts; s++) {
202 
203             /* merge the server{}s' srv_conf's */
204 
205             cf->ctx = cscfp[s]->ctx;
206 
207             if (module->merge_srv_conf) {
208                 rv = module->merge_srv_conf(cf,
209                                             ctx->srv_conf[mi],
210                                             cscfp[s]->ctx->srv_conf[mi]);
211                 if (rv != NGX_CONF_OK) {
212                     *cf = pcf;
213                     return rv;
214                 }
215             }
216         }
217     }
218 
219     *cf = pcf;
220 
221 
222     if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_mail_conf_port_t))
223         != NGX_OK)
224     {
225         return NGX_CONF_ERROR;
226     }
227 
228     listen = cmcf->listen.elts;
229 
230     for (i = 0; i < cmcf->listen.nelts; i++) {
231         if (ngx_mail_add_ports(cf, &ports, &listen[i]) != NGX_OK) {
232             return NGX_CONF_ERROR;
233         }
234     }
235 
236     return ngx_mail_optimize_servers(cf, &ports);
237 }
238 
239 
240 static ngx_int_t
241 ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
242     ngx_mail_listen_t *listen)
243 {
244     in_port_t              p;
245     ngx_uint_t             i;
246     struct sockaddr       *sa;
247     struct sockaddr_in    *sin;
248     ngx_mail_conf_port_t  *port;
249     ngx_mail_conf_addr_t  *addr;
250 #if (NGX_HAVE_INET6)
251     struct sockaddr_in6   *sin6;
252 #endif
253 
254     sa = (struct sockaddr *) &listen->sockaddr;
255 
256     switch (sa->sa_family) {
257 
258 #if (NGX_HAVE_INET6)
259     case AF_INET6:
260         sin6 = (struct sockaddr_in6 *) sa;
261         p = sin6->sin6_port;
262         break;
263 #endif
264 
265     default: /* AF_INET */
266         sin = (struct sockaddr_in *) sa;
267         p = sin->sin_port;
268         break;
269     }
270 
271     port = ports->elts;
272     for (i = 0; i < ports->nelts; i++) {
273         if (p == port[i].port && sa->sa_family == port[i].family) {
274 
275             /* a port is already in the port list */
276 
277             port = &port[i];
278             goto found;
279         }
280     }
281 
282     /* add a port to the port list */
283 
284     port = ngx_array_push(ports);
285     if (port == NULL) {
286         return NGX_ERROR;
287     }
288 
289     port->family = sa->sa_family;
290     port->port = p;
291 
292     if (ngx_array_init(&port->addrs, cf->temp_pool, 2,
293                        sizeof(ngx_mail_conf_addr_t))
294         != NGX_OK)
295     {
296         return NGX_ERROR;
297     }
298 
299 found:
300 
301     addr = ngx_array_push(&port->addrs);
302     if (addr == NULL) {
303         return NGX_ERROR;
304     }
305 
306     addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
307     addr->socklen = listen->socklen;
308     addr->ctx = listen->ctx;
309     addr->bind = listen->bind;
310     addr->wildcard = listen->wildcard;
311 #if (NGX_MAIL_SSL)
312     addr->ssl = listen->ssl;
313 #endif
314 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
315     addr->ipv6only = listen->ipv6only;
316 #endif
317 
318     return NGX_OK;
319 }
320 
321 
322 static char *
323 ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
324 {
325     ngx_uint_t             i, p, last, bind_wildcard;
326     ngx_listening_t       *ls;
327     ngx_mail_port_t       *mport;
328     ngx_mail_conf_port_t  *port;
329     ngx_mail_conf_addr_t  *addr;
330 
331     port = ports->elts;
332     for (p = 0; p < ports->nelts; p++) {
333 
334         ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
335                  sizeof(ngx_mail_conf_addr_t), ngx_mail_cmp_conf_addrs);
336 
337         addr = port[p].addrs.elts;
338         last = port[p].addrs.nelts;
339 
340         /*
341          * if there is the binding to the "*:port" then we need to bind()
342          * to the "*:port" only and ignore the other bindings
343          */
344 
345         if (addr[last - 1].wildcard) {
346             addr[last - 1].bind = 1;
347             bind_wildcard = 1;
348 
349         } else {
350             bind_wildcard = 0;
351         }
352 
353         i = 0;
354 
355         while (i < last) {
356 
357             if (bind_wildcard && !addr[i].bind) {
358                 i++;
359                 continue;
360             }
361 
362             ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen);
363             if (ls == NULL) {
364                 return NGX_CONF_ERROR;
365             }
366 
367             ls->addr_ntop = 1;
368             ls->handler = ngx_mail_init_connection;
369             ls->pool_size = 256;
370 
371             /* TODO: error_log directive */
372             ls->logp = &cf->cycle->new_log;
373             ls->log.data = &ls->addr_text;
374             ls->log.handler = ngx_accept_log_error;
375 
376 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
377             ls->ipv6only = addr[i].ipv6only;
378 #endif
379 
380             mport = ngx_palloc(cf->pool, sizeof(ngx_mail_port_t));
381             if (mport == NULL) {
382                 return NGX_CONF_ERROR;
383             }
384 
385             ls->servers = mport;
386 
387             if (i == last - 1) {
388                 mport->naddrs = last;
389 
390             } else {
391                 mport->naddrs = 1;
392                 i = 0;
393             }
394 
395             switch (ls->sockaddr->sa_family) {
396 #if (NGX_HAVE_INET6)
397             case AF_INET6:
398                 if (ngx_mail_add_addrs6(cf, mport, addr) != NGX_OK) {
399                     return NGX_CONF_ERROR;
400                 }
401                 break;
402 #endif
403             default: /* AF_INET */
404                 if (ngx_mail_add_addrs(cf, mport, addr) != NGX_OK) {
405                     return NGX_CONF_ERROR;
406                 }
407                 break;
408             }
409 
410             addr++;
411             last--;
412         }
413     }
414 
415     return NGX_CONF_OK;
416 }
417 
418 
419 static ngx_int_t
420 ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
421     ngx_mail_conf_addr_t *addr)
422 {
423     u_char              *p;
424     size_t               len;
425     ngx_uint_t           i;
426     ngx_mail_in_addr_t  *addrs;
427     struct sockaddr_in  *sin;
428     u_char               buf[NGX_SOCKADDR_STRLEN];
429 
430     mport->addrs = ngx_pcalloc(cf->pool,
431                                mport->naddrs * sizeof(ngx_mail_in_addr_t));
432     if (mport->addrs == NULL) {
433         return NGX_ERROR;
434     }
435 
436     addrs = mport->addrs;
437 
438     for (i = 0; i < mport->naddrs; i++) {
439 
440         sin = (struct sockaddr_in *) addr[i].sockaddr;
441         addrs[i].addr = sin->sin_addr.s_addr;
442 
443         addrs[i].conf.ctx = addr[i].ctx;
444 #if (NGX_MAIL_SSL)
445         addrs[i].conf.ssl = addr[i].ssl;
446 #endif
447 
448         len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1);
449 
450         p = ngx_pnalloc(cf->pool, len);
451         if (p == NULL) {
452             return NGX_ERROR;
453         }
454 
455         ngx_memcpy(p, buf, len);
456 
457         addrs[i].conf.addr_text.len = len;
458         addrs[i].conf.addr_text.data = p;
459     }
460 
461     return NGX_OK;
462 }
463 
464 
465 #if (NGX_HAVE_INET6)
466 
467 static ngx_int_t
468 ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport,
469     ngx_mail_conf_addr_t *addr)
470 {
471     u_char               *p;
472     size_t                len;
473     ngx_uint_t            i;
474     ngx_mail_in6_addr_t  *addrs6;
475     struct sockaddr_in6  *sin6;
476     u_char                buf[NGX_SOCKADDR_STRLEN];
477 
478     mport->addrs = ngx_pcalloc(cf->pool,
479                                mport->naddrs * sizeof(ngx_mail_in6_addr_t));
480     if (mport->addrs == NULL) {
481         return NGX_ERROR;
482     }
483 
484     addrs6 = mport->addrs;
485 
486     for (i = 0; i < mport->naddrs; i++) {
487 
488         sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
489         addrs6[i].addr6 = sin6->sin6_addr;
490 
491         addrs6[i].conf.ctx = addr[i].ctx;
492 #if (NGX_MAIL_SSL)
493         addrs6[i].conf.ssl = addr[i].ssl;
494 #endif
495 
496         len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1);
497 
498         p = ngx_pnalloc(cf->pool, len);
499         if (p == NULL) {
500             return NGX_ERROR;
501         }
502 
503         ngx_memcpy(p, buf, len);
504 
505         addrs6[i].conf.addr_text.len = len;
506         addrs6[i].conf.addr_text.data = p;
507     }
508 
509     return NGX_OK;
510 }
511 
512 #endif
513 
514 
515 static ngx_int_t
516 ngx_mail_cmp_conf_addrs(const void *one, const void *two)
517 {
518     ngx_mail_conf_addr_t  *first, *second;
519 
520     first = (ngx_mail_conf_addr_t *) one;
521     second = (ngx_mail_conf_addr_t *) two;
522 
523     if (first->wildcard) {
524         /* a wildcard must be the last resort, shift it to the end */
525         return 1;
526     }
527 
528     if (first->bind && !second->bind) {
529         /* shift explicit bind()ed addresses to the start */
530         return -1;
531     }
532 
533     if (!first->bind && second->bind) {
534         /* shift explicit bind()ed addresses to the start */
535         return 1;
536     }
537 
538     /* do not sort by default */
539 
540     return 0;
541 }
542 

~ [ 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.