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

Linux Cross Reference
Nginx/mail/ngx_mail_core_module.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 void *ngx_mail_core_create_main_conf(ngx_conf_t *cf);
 14 static void *ngx_mail_core_create_srv_conf(ngx_conf_t *cf);
 15 static char *ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent,
 16     void *child);
 17 static char *ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
 18     void *conf);
 19 static char *ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
 20     void *conf);
 21 static char *ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd,
 22     void *conf);
 23 static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
 24     void *conf);
 25 
 26 
 27 static ngx_command_t  ngx_mail_core_commands[] = {
 28 
 29     { ngx_string("server"),
 30       NGX_MAIL_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
 31       ngx_mail_core_server,
 32       0,
 33       0,
 34       NULL },
 35 
 36     { ngx_string("listen"),
 37       NGX_MAIL_SRV_CONF|NGX_CONF_TAKE12,
 38       ngx_mail_core_listen,
 39       NGX_MAIL_SRV_CONF_OFFSET,
 40       0,
 41       NULL },
 42 
 43     { ngx_string("protocol"),
 44       NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
 45       ngx_mail_core_protocol,
 46       NGX_MAIL_SRV_CONF_OFFSET,
 47       0,
 48       NULL },
 49 
 50     { ngx_string("so_keepalive"),
 51       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
 52       ngx_conf_set_flag_slot,
 53       NGX_MAIL_SRV_CONF_OFFSET,
 54       offsetof(ngx_mail_core_srv_conf_t, so_keepalive),
 55       NULL },
 56 
 57     { ngx_string("timeout"),
 58       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
 59       ngx_conf_set_msec_slot,
 60       NGX_MAIL_SRV_CONF_OFFSET,
 61       offsetof(ngx_mail_core_srv_conf_t, timeout),
 62       NULL },
 63 
 64     { ngx_string("server_name"),
 65       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
 66       ngx_conf_set_str_slot,
 67       NGX_MAIL_SRV_CONF_OFFSET,
 68       offsetof(ngx_mail_core_srv_conf_t, server_name),
 69       NULL },
 70 
 71     { ngx_string("resolver"),
 72       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
 73       ngx_mail_core_resolver,
 74       NGX_MAIL_SRV_CONF_OFFSET,
 75       0,
 76       NULL },
 77 
 78     { ngx_string("resolver_timeout"),
 79       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
 80       ngx_conf_set_msec_slot,
 81       NGX_MAIL_SRV_CONF_OFFSET,
 82       offsetof(ngx_mail_core_srv_conf_t, resolver_timeout),
 83       NULL },
 84 
 85       ngx_null_command
 86 };
 87 
 88 
 89 static ngx_mail_module_t  ngx_mail_core_module_ctx = {
 90     NULL,                                  /* protocol */
 91 
 92     ngx_mail_core_create_main_conf,        /* create main configuration */
 93     NULL,                                  /* init main configuration */
 94 
 95     ngx_mail_core_create_srv_conf,         /* create server configuration */
 96     ngx_mail_core_merge_srv_conf           /* merge server configuration */
 97 };
 98 
 99 
100 ngx_module_t  ngx_mail_core_module = {
101     NGX_MODULE_V1,
102     &ngx_mail_core_module_ctx,             /* module context */
103     ngx_mail_core_commands,                /* module directives */
104     NGX_MAIL_MODULE,                       /* module type */
105     NULL,                                  /* init master */
106     NULL,                                  /* init module */
107     NULL,                                  /* init process */
108     NULL,                                  /* init thread */
109     NULL,                                  /* exit thread */
110     NULL,                                  /* exit process */
111     NULL,                                  /* exit master */
112     NGX_MODULE_V1_PADDING
113 };
114 
115 
116 static void *
117 ngx_mail_core_create_main_conf(ngx_conf_t *cf)
118 {
119     ngx_mail_core_main_conf_t  *cmcf;
120 
121     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_main_conf_t));
122     if (cmcf == NULL) {
123         return NULL;
124     }
125 
126     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
127                        sizeof(ngx_mail_core_srv_conf_t *))
128         != NGX_OK)
129     {
130         return NULL;
131     }
132 
133     if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_mail_listen_t))
134         != NGX_OK)
135     {
136         return NULL;
137     }
138 
139     return cmcf;
140 }
141 
142 
143 static void *
144 ngx_mail_core_create_srv_conf(ngx_conf_t *cf)
145 {
146     ngx_mail_core_srv_conf_t  *cscf;
147 
148     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_srv_conf_t));
149     if (cscf == NULL) {
150         return NULL;
151     }
152 
153     /*
154      * set by ngx_pcalloc():
155      *
156      *     cscf->protocol = NULL;
157      */
158 
159     cscf->timeout = NGX_CONF_UNSET_MSEC;
160     cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
161     cscf->so_keepalive = NGX_CONF_UNSET;
162 
163     cscf->resolver = NGX_CONF_UNSET_PTR;
164 
165     cscf->file_name = cf->conf_file->file.name.data;
166     cscf->line = cf->conf_file->line;
167 
168     return cscf;
169 }
170 
171 
172 static char *
173 ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
174 {
175     ngx_mail_core_srv_conf_t *prev = parent;
176     ngx_mail_core_srv_conf_t *conf = child;
177 
178     ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);
179     ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout,
180                               30000);
181 
182     ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0);
183 
184 
185     ngx_conf_merge_str_value(conf->server_name, prev->server_name, "");
186 
187     if (conf->server_name.len == 0) {
188         conf->server_name = cf->cycle->hostname;
189     }
190 
191     if (conf->protocol == NULL) {
192         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
193                       "unknown mail protocol for server in %s:%ui",
194                       conf->file_name, conf->line);
195         return NGX_CONF_ERROR;
196     }
197 
198     ngx_conf_merge_ptr_value(conf->resolver, prev->resolver, NULL);
199 
200     return NGX_CONF_OK;
201 }
202 
203 
204 static char *
205 ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
206 {
207     char                       *rv;
208     void                       *mconf;
209     ngx_uint_t                  m;
210     ngx_conf_t                  pcf;
211     ngx_mail_module_t          *module;
212     ngx_mail_conf_ctx_t        *ctx, *mail_ctx;
213     ngx_mail_core_srv_conf_t   *cscf, **cscfp;
214     ngx_mail_core_main_conf_t  *cmcf;
215 
216     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t));
217     if (ctx == NULL) {
218         return NGX_CONF_ERROR;
219     }
220 
221     mail_ctx = cf->ctx;
222     ctx->main_conf = mail_ctx->main_conf;
223 
224     /* the server{}'s srv_conf */
225 
226     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module);
227     if (ctx->srv_conf == NULL) {
228         return NGX_CONF_ERROR;
229     }
230 
231     for (m = 0; ngx_modules[m]; m++) {
232         if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
233             continue;
234         }
235 
236         module = ngx_modules[m]->ctx;
237 
238         if (module->create_srv_conf) {
239             mconf = module->create_srv_conf(cf);
240             if (mconf == NULL) {
241                 return NGX_CONF_ERROR;
242             }
243 
244             ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf;
245         }
246     }
247 
248     /* the server configuration context */
249 
250     cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index];
251     cscf->ctx = ctx;
252 
253     cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index];
254 
255     cscfp = ngx_array_push(&cmcf->servers);
256     if (cscfp == NULL) {
257         return NGX_CONF_ERROR;
258     }
259 
260     *cscfp = cscf;
261 
262 
263     /* parse inside server{} */
264 
265     pcf = *cf;
266     cf->ctx = ctx;
267     cf->cmd_type = NGX_MAIL_SRV_CONF;
268 
269     rv = ngx_conf_parse(cf, NULL);
270 
271     *cf = pcf;
272 
273     return rv;
274 }
275 
276 
277 static char *
278 ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
279 {
280     ngx_mail_core_srv_conf_t  *cscf = conf;
281 
282     size_t                      len, off;
283     in_port_t                   port;
284     ngx_str_t                  *value;
285     ngx_url_t                   u;
286     ngx_uint_t                  i, m;
287     struct sockaddr            *sa;
288     ngx_mail_listen_t          *ls;
289     ngx_mail_module_t          *module;
290     struct sockaddr_in         *sin;
291     ngx_mail_core_main_conf_t  *cmcf;
292 #if (NGX_HAVE_INET6)
293     struct sockaddr_in6        *sin6;
294 #endif
295 
296     value = cf->args->elts;
297 
298     ngx_memzero(&u, sizeof(ngx_url_t));
299 
300     u.url = value[1];
301     u.listen = 1;
302 
303     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
304         if (u.err) {
305             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
306                                "%s in \"%V\" of the \"listen\" directive",
307                                u.err, &u.url);
308         }
309 
310         return NGX_CONF_ERROR;
311     }
312 
313     cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module);
314 
315     ls = cmcf->listen.elts;
316 
317     for (i = 0; i < cmcf->listen.nelts; i++) {
318 
319         sa = (struct sockaddr *) ls[i].sockaddr;
320 
321         if (sa->sa_family != u.family) {
322             continue;
323         }
324 
325         switch (sa->sa_family) {
326 
327 #if (NGX_HAVE_INET6)
328         case AF_INET6:
329             off = offsetof(struct sockaddr_in6, sin6_addr);
330             len = 16;
331             sin6 = (struct sockaddr_in6 *) sa;
332             port = sin6->sin6_port;
333             break;
334 #endif
335 
336         default: /* AF_INET */
337             off = offsetof(struct sockaddr_in, sin_addr);
338             len = 4;
339             sin = (struct sockaddr_in *) sa;
340             port = sin->sin_port;
341             break;
342         }
343 
344         if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) {
345             continue;
346         }
347 
348         if (port != u.port) {
349             continue;
350         }
351 
352         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
353                            "duplicate \"%V\" address and port pair", &u.url);
354         return NGX_CONF_ERROR;
355     }
356 
357     ls = ngx_array_push(&cmcf->listen);
358     if (ls == NULL) {
359         return NGX_CONF_ERROR;
360     }
361 
362     ngx_memzero(ls, sizeof(ngx_mail_listen_t));
363 
364     ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
365 
366     ls->socklen = u.socklen;
367     ls->wildcard = u.wildcard;
368     ls->ctx = cf->ctx;
369 
370     for (m = 0; ngx_modules[m]; m++) {
371         if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
372             continue;
373         }
374 
375         module = ngx_modules[m]->ctx;
376 
377         if (module->protocol == NULL) {
378             continue;
379         }
380 
381         for (i = 0; module->protocol->port[i]; i++) {
382             if (module->protocol->port[i] == u.port) {
383                 cscf->protocol = module->protocol;
384                 break;
385             }
386         }
387     }
388 
389     for (i = 2; i < cf->args->nelts; i++) {
390 
391         if (ngx_strcmp(value[i].data, "bind") == 0) {
392             ls->bind = 1;
393             continue;
394         }
395 
396         if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
397 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
398             struct sockaddr  *sa;
399             u_char            buf[NGX_SOCKADDR_STRLEN];
400 
401             sa = (struct sockaddr *) ls->sockaddr;
402 
403             if (sa->sa_family == AF_INET6) {
404 
405                 if (ngx_strcmp(&value[i].data[10], "n") == 0) {
406                     ls->ipv6only = 1;
407 
408                 } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
409                     ls->ipv6only = 2;
410 
411                 } else {
412                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
413                                        "invalid ipv6only flags \"%s\"",
414                                        &value[i].data[9]);
415                     return NGX_CONF_ERROR;
416                 }
417 
418                 ls->bind = 1;
419 
420             } else {
421                 len = ngx_sock_ntop(sa, buf, NGX_SOCKADDR_STRLEN, 1);
422 
423                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
424                                    "ipv6only is not supported "
425                                    "on addr \"%*s\", ignored", len, buf);
426             }
427 
428             continue;
429 #else
430             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
431                                "bind ipv6only is not supported "
432                                "on this platform");
433             return NGX_CONF_ERROR;
434 #endif
435         }
436 
437         if (ngx_strcmp(value[i].data, "ssl") == 0) {
438 #if (NGX_MAIL_SSL)
439             ls->ssl = 1;
440             continue;
441 #else
442             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
443                                "the \"ssl\" parameter requires "
444                                "ngx_mail_ssl_module");
445             return NGX_CONF_ERROR;
446 #endif
447         }
448 
449         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
450                            "the invalid \"%V\" parameter", &value[i]);
451         return NGX_CONF_ERROR;
452     }
453 
454     return NGX_CONF_OK;
455 }
456 
457 
458 static char *
459 ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
460 {
461     ngx_mail_core_srv_conf_t  *cscf = conf;
462 
463     ngx_str_t          *value;
464     ngx_uint_t          m;
465     ngx_mail_module_t  *module;
466 
467     value = cf->args->elts;
468 
469     for (m = 0; ngx_modules[m]; m++) {
470         if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
471             continue;
472         }
473 
474         module = ngx_modules[m]->ctx;
475 
476         if (module->protocol
477             && ngx_strcmp(module->protocol->name.data, value[1].data) == 0)
478         {
479             cscf->protocol = module->protocol;
480 
481             return NGX_CONF_OK;
482         }
483     }
484 
485     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
486                        "unknown protocol \"%V\"", &value[1]);
487     return NGX_CONF_ERROR;
488 }
489 
490 
491 static char *
492 ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
493 {
494     ngx_mail_core_srv_conf_t  *cscf = conf;
495 
496     ngx_url_t   u;
497     ngx_str_t  *value;
498 
499     value = cf->args->elts;
500 
501     if (cscf->resolver != NGX_CONF_UNSET_PTR) {
502         return "is duplicate";
503     }
504 
505     if (ngx_strcmp(value[1].data, "off") == 0) {
506         cscf->resolver = NULL;
507         return NGX_CONF_OK;
508     }
509 
510     ngx_memzero(&u, sizeof(ngx_url_t));
511 
512     u.host = value[1];
513     u.port = 53;
514 
515     if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
516         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
517         return NGX_CONF_ERROR;
518     }
519 
520     cscf->resolver = ngx_resolver_create(cf, &u.addrs[0]);
521     if (cscf->resolver == NULL) {
522         return NGX_CONF_OK;
523     }
524 
525     return NGX_CONF_OK;
526 }
527 
528 
529 char *
530 ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
531 {
532     char  *p = conf;
533 
534     ngx_str_t    *c, *value;
535     ngx_uint_t    i;
536     ngx_array_t  *a;
537 
538     a = (ngx_array_t *) (p + cmd->offset);
539 
540     value = cf->args->elts;
541 
542     for (i = 1; i < cf->args->nelts; i++) {
543         c = ngx_array_push(a);
544         if (c == NULL) {
545             return NGX_CONF_ERROR;
546         }
547 
548         *c = value[i];
549     }
550 
551     return NGX_CONF_OK;
552 }
553 

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