Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_mail_core_module.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 #include <ngx_mail.h>
12 
13 
14 static void *ngx_mail_core_create_main_conf(ngx_conf_t *cf);
15 static void *ngx_mail_core_create_srv_conf(ngx_conf_t *cf);
16 static char *ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent,
17  void *child);
18 static char *ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
19  void *conf);
20 static char *ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
21  void *conf);
22 static char *ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd,
23  void *conf);
24 static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
25  void *conf);
26 
27 
28 static ngx_conf_deprecated_t ngx_conf_deprecated_so_keepalive = {
29  ngx_conf_deprecated, "so_keepalive",
30  "so_keepalive\" parameter of the \"listen"
31 };
32 
33 
34 static ngx_command_t ngx_mail_core_commands[] = {
35 
36  { ngx_string("server"),
38  ngx_mail_core_server,
39  0,
40  0,
41  NULL },
42 
43  { ngx_string("listen"),
45  ngx_mail_core_listen,
47  0,
48  NULL },
49 
50  { ngx_string("protocol"),
52  ngx_mail_core_protocol,
54  0,
55  NULL },
56 
57  { ngx_string("so_keepalive"),
61  offsetof(ngx_mail_core_srv_conf_t, so_keepalive),
62  &ngx_conf_deprecated_so_keepalive },
63 
64  { ngx_string("timeout"),
68  offsetof(ngx_mail_core_srv_conf_t, timeout),
69  NULL },
70 
71  { ngx_string("server_name"),
75  offsetof(ngx_mail_core_srv_conf_t, server_name),
76  NULL },
77 
78  { ngx_string("resolver"),
80  ngx_mail_core_resolver,
82  0,
83  NULL },
84 
85  { ngx_string("resolver_timeout"),
89  offsetof(ngx_mail_core_srv_conf_t, resolver_timeout),
90  NULL },
91 
93 };
94 
95 
96 static ngx_mail_module_t ngx_mail_core_module_ctx = {
97  NULL, /* protocol */
98 
99  ngx_mail_core_create_main_conf, /* create main configuration */
100  NULL, /* init main configuration */
101 
102  ngx_mail_core_create_srv_conf, /* create server configuration */
103  ngx_mail_core_merge_srv_conf /* merge server configuration */
104 };
105 
106 
109  &ngx_mail_core_module_ctx, /* module context */
110  ngx_mail_core_commands, /* module directives */
111  NGX_MAIL_MODULE, /* module type */
112  NULL, /* init master */
113  NULL, /* init module */
114  NULL, /* init process */
115  NULL, /* init thread */
116  NULL, /* exit thread */
117  NULL, /* exit process */
118  NULL, /* exit master */
120 };
121 
122 
123 static void *
124 ngx_mail_core_create_main_conf(ngx_conf_t *cf)
125 {
127 
128  cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_main_conf_t));
129  if (cmcf == NULL) {
130  return NULL;
131  }
132 
133  if (ngx_array_init(&cmcf->servers, cf->pool, 4,
134  sizeof(ngx_mail_core_srv_conf_t *))
135  != NGX_OK)
136  {
137  return NULL;
138  }
139 
140  if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_mail_listen_t))
141  != NGX_OK)
142  {
143  return NULL;
144  }
145 
146  return cmcf;
147 }
148 
149 
150 static void *
151 ngx_mail_core_create_srv_conf(ngx_conf_t *cf)
152 {
154 
155  cscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_srv_conf_t));
156  if (cscf == NULL) {
157  return NULL;
158  }
159 
160  /*
161  * set by ngx_pcalloc():
162  *
163  * cscf->protocol = NULL;
164  */
165 
169 
171 
172  cscf->file_name = cf->conf_file->file.name.data;
173  cscf->line = cf->conf_file->line;
174 
175  return cscf;
176 }
177 
178 
179 static char *
180 ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
181 {
182  ngx_mail_core_srv_conf_t *prev = parent;
183  ngx_mail_core_srv_conf_t *conf = child;
184 
185  ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);
187  30000);
188 
190 
191 
193 
194  if (conf->server_name.len == 0) {
195  conf->server_name = cf->cycle->hostname;
196  }
197 
198  if (conf->protocol == NULL) {
200  "unknown mail protocol for server in %s:%ui",
201  conf->file_name, conf->line);
202  return NGX_CONF_ERROR;
203  }
204 
205  ngx_conf_merge_ptr_value(conf->resolver, prev->resolver, NULL);
206 
207  return NGX_CONF_OK;
208 }
209 
210 
211 static char *
212 ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
213 {
214  char *rv;
215  void *mconf;
216  ngx_uint_t m;
217  ngx_conf_t pcf;
218  ngx_mail_module_t *module;
219  ngx_mail_conf_ctx_t *ctx, *mail_ctx;
220  ngx_mail_core_srv_conf_t *cscf, **cscfp;
222 
223  ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t));
224  if (ctx == NULL) {
225  return NGX_CONF_ERROR;
226  }
227 
228  mail_ctx = cf->ctx;
229  ctx->main_conf = mail_ctx->main_conf;
230 
231  /* the server{}'s srv_conf */
232 
233  ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module);
234  if (ctx->srv_conf == NULL) {
235  return NGX_CONF_ERROR;
236  }
237 
238  for (m = 0; ngx_modules[m]; m++) {
239  if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
240  continue;
241  }
242 
243  module = ngx_modules[m]->ctx;
244 
245  if (module->create_srv_conf) {
246  mconf = module->create_srv_conf(cf);
247  if (mconf == NULL) {
248  return NGX_CONF_ERROR;
249  }
250 
251  ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf;
252  }
253  }
254 
255  /* the server configuration context */
256 
257  cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index];
258  cscf->ctx = ctx;
259 
260  cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index];
261 
262  cscfp = ngx_array_push(&cmcf->servers);
263  if (cscfp == NULL) {
264  return NGX_CONF_ERROR;
265  }
266 
267  *cscfp = cscf;
268 
269 
270  /* parse inside server{} */
271 
272  pcf = *cf;
273  cf->ctx = ctx;
275 
276  rv = ngx_conf_parse(cf, NULL);
277 
278  *cf = pcf;
279 
280  return rv;
281 }
282 
283 
284 static char *
285 ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
286 {
287  ngx_mail_core_srv_conf_t *cscf = conf;
288 
289  size_t len, off;
290  in_port_t port;
291  ngx_str_t *value;
292  ngx_url_t u;
293  ngx_uint_t i, m;
294  struct sockaddr *sa;
295  ngx_mail_listen_t *ls;
296  ngx_mail_module_t *module;
297  struct sockaddr_in *sin;
299 #if (NGX_HAVE_INET6)
300  struct sockaddr_in6 *sin6;
301 #endif
302 
303  value = cf->args->elts;
304 
305  ngx_memzero(&u, sizeof(ngx_url_t));
306 
307  u.url = value[1];
308  u.listen = 1;
309 
310  if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
311  if (u.err) {
313  "%s in \"%V\" of the \"listen\" directive",
314  u.err, &u.url);
315  }
316 
317  return NGX_CONF_ERROR;
318  }
319 
320  cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module);
321 
322  ls = cmcf->listen.elts;
323 
324  for (i = 0; i < cmcf->listen.nelts; i++) {
325 
326  sa = (struct sockaddr *) ls[i].sockaddr;
327 
328  if (sa->sa_family != u.family) {
329  continue;
330  }
331 
332  switch (sa->sa_family) {
333 
334 #if (NGX_HAVE_INET6)
335  case AF_INET6:
336  off = offsetof(struct sockaddr_in6, sin6_addr);
337  len = 16;
338  sin6 = (struct sockaddr_in6 *) sa;
339  port = sin6->sin6_port;
340  break;
341 #endif
342 
343 #if (NGX_HAVE_UNIX_DOMAIN)
344  case AF_UNIX:
345  off = offsetof(struct sockaddr_un, sun_path);
346  len = sizeof(((struct sockaddr_un *) sa)->sun_path);
347  port = 0;
348  break;
349 #endif
350 
351  default: /* AF_INET */
352  off = offsetof(struct sockaddr_in, sin_addr);
353  len = 4;
354  sin = (struct sockaddr_in *) sa;
355  port = sin->sin_port;
356  break;
357  }
358 
359  if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) {
360  continue;
361  }
362 
363  if (port != u.port) {
364  continue;
365  }
366 
368  "duplicate \"%V\" address and port pair", &u.url);
369  return NGX_CONF_ERROR;
370  }
371 
372  ls = ngx_array_push(&cmcf->listen);
373  if (ls == NULL) {
374  return NGX_CONF_ERROR;
375  }
376 
377  ngx_memzero(ls, sizeof(ngx_mail_listen_t));
378 
379  ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
380 
381  ls->socklen = u.socklen;
382  ls->wildcard = u.wildcard;
383  ls->ctx = cf->ctx;
384 
385 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
386  ls->ipv6only = 1;
387 #endif
388 
389  if (cscf->protocol == NULL) {
390  for (m = 0; ngx_modules[m]; m++) {
391  if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
392  continue;
393  }
394 
395  module = ngx_modules[m]->ctx;
396 
397  if (module->protocol == NULL) {
398  continue;
399  }
400 
401  for (i = 0; module->protocol->port[i]; i++) {
402  if (module->protocol->port[i] == u.port) {
403  cscf->protocol = module->protocol;
404  break;
405  }
406  }
407  }
408  }
409 
410  for (i = 2; i < cf->args->nelts; i++) {
411 
412  if (ngx_strcmp(value[i].data, "bind") == 0) {
413  ls->bind = 1;
414  continue;
415  }
416 
417  if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
418 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
419  struct sockaddr *sa;
420  u_char buf[NGX_SOCKADDR_STRLEN];
421 
422  sa = (struct sockaddr *) ls->sockaddr;
423 
424  if (sa->sa_family == AF_INET6) {
425 
426  if (ngx_strcmp(&value[i].data[10], "n") == 0) {
427  ls->ipv6only = 1;
428 
429  } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
430  ls->ipv6only = 0;
431 
432  } else {
434  "invalid ipv6only flags \"%s\"",
435  &value[i].data[9]);
436  return NGX_CONF_ERROR;
437  }
438 
439  ls->bind = 1;
440 
441  } else {
442  len = ngx_sock_ntop(sa, buf, NGX_SOCKADDR_STRLEN, 1);
443 
445  "ipv6only is not supported "
446  "on addr \"%*s\", ignored", len, buf);
447  }
448 
449  continue;
450 #else
452  "bind ipv6only is not supported "
453  "on this platform");
454  return NGX_CONF_ERROR;
455 #endif
456  }
457 
458  if (ngx_strcmp(value[i].data, "ssl") == 0) {
459 #if (NGX_MAIL_SSL)
460  ls->ssl = 1;
461  continue;
462 #else
464  "the \"ssl\" parameter requires "
465  "ngx_mail_ssl_module");
466  return NGX_CONF_ERROR;
467 #endif
468  }
469 
470  if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {
471 
472  if (ngx_strcmp(&value[i].data[13], "on") == 0) {
473  ls->so_keepalive = 1;
474 
475  } else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
476  ls->so_keepalive = 2;
477 
478  } else {
479 
480 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
481  u_char *p, *end;
482  ngx_str_t s;
483 
484  end = value[i].data + value[i].len;
485  s.data = value[i].data + 13;
486 
487  p = ngx_strlchr(s.data, end, ':');
488  if (p == NULL) {
489  p = end;
490  }
491 
492  if (p > s.data) {
493  s.len = p - s.data;
494 
495  ls->tcp_keepidle = ngx_parse_time(&s, 1);
496  if (ls->tcp_keepidle == (time_t) NGX_ERROR) {
497  goto invalid_so_keepalive;
498  }
499  }
500 
501  s.data = (p < end) ? (p + 1) : end;
502 
503  p = ngx_strlchr(s.data, end, ':');
504  if (p == NULL) {
505  p = end;
506  }
507 
508  if (p > s.data) {
509  s.len = p - s.data;
510 
511  ls->tcp_keepintvl = ngx_parse_time(&s, 1);
512  if (ls->tcp_keepintvl == (time_t) NGX_ERROR) {
513  goto invalid_so_keepalive;
514  }
515  }
516 
517  s.data = (p < end) ? (p + 1) : end;
518 
519  if (s.data < end) {
520  s.len = end - s.data;
521 
522  ls->tcp_keepcnt = ngx_atoi(s.data, s.len);
523  if (ls->tcp_keepcnt == NGX_ERROR) {
524  goto invalid_so_keepalive;
525  }
526  }
527 
528  if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0
529  && ls->tcp_keepcnt == 0)
530  {
531  goto invalid_so_keepalive;
532  }
533 
534  ls->so_keepalive = 1;
535 
536 #else
537 
539  "the \"so_keepalive\" parameter accepts "
540  "only \"on\" or \"off\" on this platform");
541  return NGX_CONF_ERROR;
542 
543 #endif
544  }
545 
546  ls->bind = 1;
547 
548  continue;
549 
550 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
551  invalid_so_keepalive:
552 
554  "invalid so_keepalive value: \"%s\"",
555  &value[i].data[13]);
556  return NGX_CONF_ERROR;
557 #endif
558  }
559 
561  "the invalid \"%V\" parameter", &value[i]);
562  return NGX_CONF_ERROR;
563  }
564 
565  return NGX_CONF_OK;
566 }
567 
568 
569 static char *
570 ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
571 {
572  ngx_mail_core_srv_conf_t *cscf = conf;
573 
574  ngx_str_t *value;
575  ngx_uint_t m;
576  ngx_mail_module_t *module;
577 
578  value = cf->args->elts;
579 
580  for (m = 0; ngx_modules[m]; m++) {
581  if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
582  continue;
583  }
584 
585  module = ngx_modules[m]->ctx;
586 
587  if (module->protocol
588  && ngx_strcmp(module->protocol->name.data, value[1].data) == 0)
589  {
590  cscf->protocol = module->protocol;
591 
592  return NGX_CONF_OK;
593  }
594  }
595 
597  "unknown protocol \"%V\"", &value[1]);
598  return NGX_CONF_ERROR;
599 }
600 
601 
602 static char *
603 ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
604 {
605  ngx_mail_core_srv_conf_t *cscf = conf;
606 
607  ngx_str_t *value;
608 
609  value = cf->args->elts;
610 
611  if (cscf->resolver != NGX_CONF_UNSET_PTR) {
612  return "is duplicate";
613  }
614 
615  if (ngx_strcmp(value[1].data, "off") == 0) {
616  cscf->resolver = NULL;
617  return NGX_CONF_OK;
618  }
619 
620  cscf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
621  if (cscf->resolver == NULL) {
622  return NGX_CONF_ERROR;
623  }
624 
625  return NGX_CONF_OK;
626 }
627 
628 
629 char *
631 {
632  char *p = conf;
633 
634  ngx_str_t *c, *value;
635  ngx_uint_t i;
636  ngx_array_t *a;
637 
638  a = (ngx_array_t *) (p + cmd->offset);
639 
640  value = cf->args->elts;
641 
642  for (i = 1; i < cf->args->nelts; i++) {
643  c = ngx_array_push(a);
644  if (c == NULL) {
645  return NGX_CONF_ERROR;
646  }
647 
648  *c = value[i];
649  }
650 
651  return NGX_CONF_OK;
652 }