Annotation of embedaddon/nginx/src/mail/ngx_mail_core_module.c, revision 1.1.1.1
1.1 misho 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"),
37: NGX_MAIL_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
38: ngx_mail_core_server,
39: 0,
40: 0,
41: NULL },
42:
43: { ngx_string("listen"),
44: NGX_MAIL_SRV_CONF|NGX_CONF_TAKE12,
45: ngx_mail_core_listen,
46: NGX_MAIL_SRV_CONF_OFFSET,
47: 0,
48: NULL },
49:
50: { ngx_string("protocol"),
51: NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
52: ngx_mail_core_protocol,
53: NGX_MAIL_SRV_CONF_OFFSET,
54: 0,
55: NULL },
56:
57: { ngx_string("so_keepalive"),
58: NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
59: ngx_conf_set_flag_slot,
60: NGX_MAIL_SRV_CONF_OFFSET,
61: offsetof(ngx_mail_core_srv_conf_t, so_keepalive),
62: &ngx_conf_deprecated_so_keepalive },
63:
64: { ngx_string("timeout"),
65: NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
66: ngx_conf_set_msec_slot,
67: NGX_MAIL_SRV_CONF_OFFSET,
68: offsetof(ngx_mail_core_srv_conf_t, timeout),
69: NULL },
70:
71: { ngx_string("server_name"),
72: NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
73: ngx_conf_set_str_slot,
74: NGX_MAIL_SRV_CONF_OFFSET,
75: offsetof(ngx_mail_core_srv_conf_t, server_name),
76: NULL },
77:
78: { ngx_string("resolver"),
79: NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
80: ngx_mail_core_resolver,
81: NGX_MAIL_SRV_CONF_OFFSET,
82: 0,
83: NULL },
84:
85: { ngx_string("resolver_timeout"),
86: NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
87: ngx_conf_set_msec_slot,
88: NGX_MAIL_SRV_CONF_OFFSET,
89: offsetof(ngx_mail_core_srv_conf_t, resolver_timeout),
90: NULL },
91:
92: ngx_null_command
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:
107: ngx_module_t ngx_mail_core_module = {
108: NGX_MODULE_V1,
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 */
119: NGX_MODULE_V1_PADDING
120: };
121:
122:
123: static void *
124: ngx_mail_core_create_main_conf(ngx_conf_t *cf)
125: {
126: ngx_mail_core_main_conf_t *cmcf;
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: {
153: ngx_mail_core_srv_conf_t *cscf;
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:
166: cscf->timeout = NGX_CONF_UNSET_MSEC;
167: cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
168: cscf->so_keepalive = NGX_CONF_UNSET;
169:
170: cscf->resolver = NGX_CONF_UNSET_PTR;
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);
186: ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout,
187: 30000);
188:
189: ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0);
190:
191:
192: ngx_conf_merge_str_value(conf->server_name, prev->server_name, "");
193:
194: if (conf->server_name.len == 0) {
195: conf->server_name = cf->cycle->hostname;
196: }
197:
198: if (conf->protocol == NULL) {
199: ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
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;
221: ngx_mail_core_main_conf_t *cmcf;
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;
274: cf->cmd_type = NGX_MAIL_SRV_CONF;
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;
298: ngx_mail_core_main_conf_t *cmcf;
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) {
312: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
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:
367: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
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 {
433: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
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:
444: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
445: "ipv6only is not supported "
446: "on addr \"%*s\", ignored", len, buf);
447: }
448:
449: continue;
450: #else
451: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
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
463: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
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:
538: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
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:
553: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
554: "invalid so_keepalive value: \"%s\"",
555: &value[i].data[13]);
556: return NGX_CONF_ERROR;
557: #endif
558: }
559:
560: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
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:
596: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
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 *
630: ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>