Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 #include <ngx_mail.h>
0012 
0013 
0014 static void *ngx_mail_core_create_main_conf(ngx_conf_t *cf);
0015 static void *ngx_mail_core_create_srv_conf(ngx_conf_t *cf);
0016 static char *ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent,
0017     void *child);
0018 static char *ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
0019     void *conf);
0020 static char *ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
0021     void *conf);
0022 static char *ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd,
0023     void *conf);
0024 static char *ngx_mail_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
0025     void *conf);
0026 static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
0027     void *conf);
0028 
0029 
0030 static ngx_command_t  ngx_mail_core_commands[] = {
0031 
0032     { ngx_string("server"),
0033       NGX_MAIL_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
0034       ngx_mail_core_server,
0035       0,
0036       0,
0037       NULL },
0038 
0039     { ngx_string("listen"),
0040       NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
0041       ngx_mail_core_listen,
0042       NGX_MAIL_SRV_CONF_OFFSET,
0043       0,
0044       NULL },
0045 
0046     { ngx_string("protocol"),
0047       NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
0048       ngx_mail_core_protocol,
0049       NGX_MAIL_SRV_CONF_OFFSET,
0050       0,
0051       NULL },
0052 
0053     { ngx_string("timeout"),
0054       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
0055       ngx_conf_set_msec_slot,
0056       NGX_MAIL_SRV_CONF_OFFSET,
0057       offsetof(ngx_mail_core_srv_conf_t, timeout),
0058       NULL },
0059 
0060     { ngx_string("server_name"),
0061       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
0062       ngx_conf_set_str_slot,
0063       NGX_MAIL_SRV_CONF_OFFSET,
0064       offsetof(ngx_mail_core_srv_conf_t, server_name),
0065       NULL },
0066 
0067     { ngx_string("error_log"),
0068       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
0069       ngx_mail_core_error_log,
0070       NGX_MAIL_SRV_CONF_OFFSET,
0071       0,
0072       NULL },
0073 
0074     { ngx_string("resolver"),
0075       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
0076       ngx_mail_core_resolver,
0077       NGX_MAIL_SRV_CONF_OFFSET,
0078       0,
0079       NULL },
0080 
0081     { ngx_string("resolver_timeout"),
0082       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
0083       ngx_conf_set_msec_slot,
0084       NGX_MAIL_SRV_CONF_OFFSET,
0085       offsetof(ngx_mail_core_srv_conf_t, resolver_timeout),
0086       NULL },
0087 
0088       ngx_null_command
0089 };
0090 
0091 
0092 static ngx_mail_module_t  ngx_mail_core_module_ctx = {
0093     NULL,                                  /* protocol */
0094 
0095     ngx_mail_core_create_main_conf,        /* create main configuration */
0096     NULL,                                  /* init main configuration */
0097 
0098     ngx_mail_core_create_srv_conf,         /* create server configuration */
0099     ngx_mail_core_merge_srv_conf           /* merge server configuration */
0100 };
0101 
0102 
0103 ngx_module_t  ngx_mail_core_module = {
0104     NGX_MODULE_V1,
0105     &ngx_mail_core_module_ctx,             /* module context */
0106     ngx_mail_core_commands,                /* module directives */
0107     NGX_MAIL_MODULE,                       /* module type */
0108     NULL,                                  /* init master */
0109     NULL,                                  /* init module */
0110     NULL,                                  /* init process */
0111     NULL,                                  /* init thread */
0112     NULL,                                  /* exit thread */
0113     NULL,                                  /* exit process */
0114     NULL,                                  /* exit master */
0115     NGX_MODULE_V1_PADDING
0116 };
0117 
0118 
0119 static void *
0120 ngx_mail_core_create_main_conf(ngx_conf_t *cf)
0121 {
0122     ngx_mail_core_main_conf_t  *cmcf;
0123 
0124     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_main_conf_t));
0125     if (cmcf == NULL) {
0126         return NULL;
0127     }
0128 
0129     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
0130                        sizeof(ngx_mail_core_srv_conf_t *))
0131         != NGX_OK)
0132     {
0133         return NULL;
0134     }
0135 
0136     if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_mail_listen_t))
0137         != NGX_OK)
0138     {
0139         return NULL;
0140     }
0141 
0142     return cmcf;
0143 }
0144 
0145 
0146 static void *
0147 ngx_mail_core_create_srv_conf(ngx_conf_t *cf)
0148 {
0149     ngx_mail_core_srv_conf_t  *cscf;
0150 
0151     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_core_srv_conf_t));
0152     if (cscf == NULL) {
0153         return NULL;
0154     }
0155 
0156     /*
0157      * set by ngx_pcalloc():
0158      *
0159      *     cscf->protocol = NULL;
0160      *     cscf->error_log = NULL;
0161      */
0162 
0163     cscf->timeout = NGX_CONF_UNSET_MSEC;
0164     cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
0165 
0166     cscf->resolver = NGX_CONF_UNSET_PTR;
0167 
0168     cscf->file_name = cf->conf_file->file.name.data;
0169     cscf->line = cf->conf_file->line;
0170 
0171     return cscf;
0172 }
0173 
0174 
0175 static char *
0176 ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
0177 {
0178     ngx_mail_core_srv_conf_t *prev = parent;
0179     ngx_mail_core_srv_conf_t *conf = child;
0180 
0181     ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);
0182     ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout,
0183                               30000);
0184 
0185 
0186     ngx_conf_merge_str_value(conf->server_name, prev->server_name, "");
0187 
0188     if (conf->server_name.len == 0) {
0189         conf->server_name = cf->cycle->hostname;
0190     }
0191 
0192     if (conf->protocol == NULL) {
0193         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0194                       "unknown mail protocol for server in %s:%ui",
0195                       conf->file_name, conf->line);
0196         return NGX_CONF_ERROR;
0197     }
0198 
0199     if (conf->error_log == NULL) {
0200         if (prev->error_log) {
0201             conf->error_log = prev->error_log;
0202         } else {
0203             conf->error_log = &cf->cycle->new_log;
0204         }
0205     }
0206 
0207     ngx_conf_merge_ptr_value(conf->resolver, prev->resolver, NULL);
0208 
0209     return NGX_CONF_OK;
0210 }
0211 
0212 
0213 static char *
0214 ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0215 {
0216     char                       *rv;
0217     void                       *mconf;
0218     ngx_uint_t                  m;
0219     ngx_conf_t                  pcf;
0220     ngx_mail_module_t          *module;
0221     ngx_mail_conf_ctx_t        *ctx, *mail_ctx;
0222     ngx_mail_core_srv_conf_t   *cscf, **cscfp;
0223     ngx_mail_core_main_conf_t  *cmcf;
0224 
0225     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t));
0226     if (ctx == NULL) {
0227         return NGX_CONF_ERROR;
0228     }
0229 
0230     mail_ctx = cf->ctx;
0231     ctx->main_conf = mail_ctx->main_conf;
0232 
0233     /* the server{}'s srv_conf */
0234 
0235     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module);
0236     if (ctx->srv_conf == NULL) {
0237         return NGX_CONF_ERROR;
0238     }
0239 
0240     for (m = 0; cf->cycle->modules[m]; m++) {
0241         if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) {
0242             continue;
0243         }
0244 
0245         module = cf->cycle->modules[m]->ctx;
0246 
0247         if (module->create_srv_conf) {
0248             mconf = module->create_srv_conf(cf);
0249             if (mconf == NULL) {
0250                 return NGX_CONF_ERROR;
0251             }
0252 
0253             ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf;
0254         }
0255     }
0256 
0257     /* the server configuration context */
0258 
0259     cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index];
0260     cscf->ctx = ctx;
0261 
0262     cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index];
0263 
0264     cscfp = ngx_array_push(&cmcf->servers);
0265     if (cscfp == NULL) {
0266         return NGX_CONF_ERROR;
0267     }
0268 
0269     *cscfp = cscf;
0270 
0271 
0272     /* parse inside server{} */
0273 
0274     pcf = *cf;
0275     cf->ctx = ctx;
0276     cf->cmd_type = NGX_MAIL_SRV_CONF;
0277 
0278     rv = ngx_conf_parse(cf, NULL);
0279 
0280     *cf = pcf;
0281 
0282     if (rv == NGX_CONF_OK && !cscf->listen) {
0283         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0284                       "no \"listen\" is defined for server in %s:%ui",
0285                       cscf->file_name, cscf->line);
0286         return NGX_CONF_ERROR;
0287     }
0288 
0289     return rv;
0290 }
0291 
0292 
0293 static char *
0294 ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0295 {
0296     ngx_mail_core_srv_conf_t  *cscf = conf;
0297 
0298     ngx_str_t                  *value;
0299     ngx_url_t                   u;
0300     ngx_uint_t                  i, m;
0301     ngx_mail_listen_t          *ls;
0302     ngx_mail_module_t          *module;
0303     ngx_mail_core_main_conf_t  *cmcf;
0304 
0305     cscf->listen = 1;
0306 
0307     value = cf->args->elts;
0308 
0309     ngx_memzero(&u, sizeof(ngx_url_t));
0310 
0311     u.url = value[1];
0312     u.listen = 1;
0313 
0314     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
0315         if (u.err) {
0316             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0317                                "%s in \"%V\" of the \"listen\" directive",
0318                                u.err, &u.url);
0319         }
0320 
0321         return NGX_CONF_ERROR;
0322     }
0323 
0324     cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module);
0325 
0326     ls = cmcf->listen.elts;
0327 
0328     for (i = 0; i < cmcf->listen.nelts; i++) {
0329 
0330         if (ngx_cmp_sockaddr(&ls[i].sockaddr.sockaddr, ls[i].socklen,
0331                              (struct sockaddr *) &u.sockaddr, u.socklen, 1)
0332             != NGX_OK)
0333         {
0334             continue;
0335         }
0336 
0337         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0338                            "duplicate \"%V\" address and port pair", &u.url);
0339         return NGX_CONF_ERROR;
0340     }
0341 
0342     ls = ngx_array_push(&cmcf->listen);
0343     if (ls == NULL) {
0344         return NGX_CONF_ERROR;
0345     }
0346 
0347     ngx_memzero(ls, sizeof(ngx_mail_listen_t));
0348 
0349     ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen);
0350 
0351     ls->socklen = u.socklen;
0352     ls->backlog = NGX_LISTEN_BACKLOG;
0353     ls->wildcard = u.wildcard;
0354     ls->ctx = cf->ctx;
0355 
0356 #if (NGX_HAVE_INET6)
0357     ls->ipv6only = 1;
0358 #endif
0359 
0360     if (cscf->protocol == NULL) {
0361         for (m = 0; cf->cycle->modules[m]; m++) {
0362             if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) {
0363                 continue;
0364             }
0365 
0366             module = cf->cycle->modules[m]->ctx;
0367 
0368             if (module->protocol == NULL) {
0369                 continue;
0370             }
0371 
0372             for (i = 0; module->protocol->port[i]; i++) {
0373                 if (module->protocol->port[i] == u.port) {
0374                     cscf->protocol = module->protocol;
0375                     break;
0376                 }
0377             }
0378         }
0379     }
0380 
0381     for (i = 2; i < cf->args->nelts; i++) {
0382 
0383         if (ngx_strcmp(value[i].data, "bind") == 0) {
0384             ls->bind = 1;
0385             continue;
0386         }
0387 
0388         if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
0389             ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
0390             ls->bind = 1;
0391 
0392             if (ls->backlog == NGX_ERROR || ls->backlog == 0) {
0393                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0394                                    "invalid backlog \"%V\"", &value[i]);
0395                 return NGX_CONF_ERROR;
0396             }
0397 
0398             continue;
0399         }
0400 
0401         if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
0402 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
0403             size_t  len;
0404             u_char  buf[NGX_SOCKADDR_STRLEN];
0405 
0406             if (ls->sockaddr.sockaddr.sa_family == AF_INET6) {
0407 
0408                 if (ngx_strcmp(&value[i].data[10], "n") == 0) {
0409                     ls->ipv6only = 1;
0410 
0411                 } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
0412                     ls->ipv6only = 0;
0413 
0414                 } else {
0415                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0416                                        "invalid ipv6only flags \"%s\"",
0417                                        &value[i].data[9]);
0418                     return NGX_CONF_ERROR;
0419                 }
0420 
0421                 ls->bind = 1;
0422 
0423             } else {
0424                 len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf,
0425                                     NGX_SOCKADDR_STRLEN, 1);
0426 
0427                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0428                                    "ipv6only is not supported "
0429                                    "on addr \"%*s\", ignored", len, buf);
0430             }
0431 
0432             continue;
0433 #else
0434             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0435                                "bind ipv6only is not supported "
0436                                "on this platform");
0437             return NGX_CONF_ERROR;
0438 #endif
0439         }
0440 
0441         if (ngx_strcmp(value[i].data, "ssl") == 0) {
0442 #if (NGX_MAIL_SSL)
0443             ls->ssl = 1;
0444             continue;
0445 #else
0446             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0447                                "the \"ssl\" parameter requires "
0448                                "ngx_mail_ssl_module");
0449             return NGX_CONF_ERROR;
0450 #endif
0451         }
0452 
0453         if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {
0454 
0455             if (ngx_strcmp(&value[i].data[13], "on") == 0) {
0456                 ls->so_keepalive = 1;
0457 
0458             } else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
0459                 ls->so_keepalive = 2;
0460 
0461             } else {
0462 
0463 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0464                 u_char     *p, *end;
0465                 ngx_str_t   s;
0466 
0467                 end = value[i].data + value[i].len;
0468                 s.data = value[i].data + 13;
0469 
0470                 p = ngx_strlchr(s.data, end, ':');
0471                 if (p == NULL) {
0472                     p = end;
0473                 }
0474 
0475                 if (p > s.data) {
0476                     s.len = p - s.data;
0477 
0478                     ls->tcp_keepidle = ngx_parse_time(&s, 1);
0479                     if (ls->tcp_keepidle == (time_t) NGX_ERROR) {
0480                         goto invalid_so_keepalive;
0481                     }
0482                 }
0483 
0484                 s.data = (p < end) ? (p + 1) : end;
0485 
0486                 p = ngx_strlchr(s.data, end, ':');
0487                 if (p == NULL) {
0488                     p = end;
0489                 }
0490 
0491                 if (p > s.data) {
0492                     s.len = p - s.data;
0493 
0494                     ls->tcp_keepintvl = ngx_parse_time(&s, 1);
0495                     if (ls->tcp_keepintvl == (time_t) NGX_ERROR) {
0496                         goto invalid_so_keepalive;
0497                     }
0498                 }
0499 
0500                 s.data = (p < end) ? (p + 1) : end;
0501 
0502                 if (s.data < end) {
0503                     s.len = end - s.data;
0504 
0505                     ls->tcp_keepcnt = ngx_atoi(s.data, s.len);
0506                     if (ls->tcp_keepcnt == NGX_ERROR) {
0507                         goto invalid_so_keepalive;
0508                     }
0509                 }
0510 
0511                 if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0
0512                     && ls->tcp_keepcnt == 0)
0513                 {
0514                     goto invalid_so_keepalive;
0515                 }
0516 
0517                 ls->so_keepalive = 1;
0518 
0519 #else
0520 
0521                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0522                                    "the \"so_keepalive\" parameter accepts "
0523                                    "only \"on\" or \"off\" on this platform");
0524                 return NGX_CONF_ERROR;
0525 
0526 #endif
0527             }
0528 
0529             ls->bind = 1;
0530 
0531             continue;
0532 
0533 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0534         invalid_so_keepalive:
0535 
0536             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0537                                "invalid so_keepalive value: \"%s\"",
0538                                &value[i].data[13]);
0539             return NGX_CONF_ERROR;
0540 #endif
0541         }
0542 
0543         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0544                            "the invalid \"%V\" parameter", &value[i]);
0545         return NGX_CONF_ERROR;
0546     }
0547 
0548     return NGX_CONF_OK;
0549 }
0550 
0551 
0552 static char *
0553 ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0554 {
0555     ngx_mail_core_srv_conf_t  *cscf = conf;
0556 
0557     ngx_str_t          *value;
0558     ngx_uint_t          m;
0559     ngx_mail_module_t  *module;
0560 
0561     value = cf->args->elts;
0562 
0563     for (m = 0; cf->cycle->modules[m]; m++) {
0564         if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) {
0565             continue;
0566         }
0567 
0568         module = cf->cycle->modules[m]->ctx;
0569 
0570         if (module->protocol
0571             && ngx_strcmp(module->protocol->name.data, value[1].data) == 0)
0572         {
0573             cscf->protocol = module->protocol;
0574 
0575             return NGX_CONF_OK;
0576         }
0577     }
0578 
0579     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0580                        "unknown protocol \"%V\"", &value[1]);
0581     return NGX_CONF_ERROR;
0582 }
0583 
0584 
0585 static char *
0586 ngx_mail_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0587 {
0588     ngx_mail_core_srv_conf_t  *cscf = conf;
0589 
0590     return ngx_log_set_log(cf, &cscf->error_log);
0591 }
0592 
0593 
0594 static char *
0595 ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0596 {
0597     ngx_mail_core_srv_conf_t  *cscf = conf;
0598 
0599     ngx_str_t  *value;
0600 
0601     value = cf->args->elts;
0602 
0603     if (cscf->resolver != NGX_CONF_UNSET_PTR) {
0604         return "is duplicate";
0605     }
0606 
0607     if (ngx_strcmp(value[1].data, "off") == 0) {
0608         cscf->resolver = NULL;
0609         return NGX_CONF_OK;
0610     }
0611 
0612     cscf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
0613     if (cscf->resolver == NULL) {
0614         return NGX_CONF_ERROR;
0615     }
0616 
0617     return NGX_CONF_OK;
0618 }
0619 
0620 
0621 char *
0622 ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0623 {
0624     char  *p = conf;
0625 
0626     ngx_str_t    *c, *value;
0627     ngx_uint_t    i;
0628     ngx_array_t  *a;
0629 
0630     a = (ngx_array_t *) (p + cmd->offset);
0631 
0632     value = cf->args->elts;
0633 
0634     for (i = 1; i < cf->args->nelts; i++) {
0635         c = ngx_array_push(a);
0636         if (c == NULL) {
0637             return NGX_CONF_ERROR;
0638         }
0639 
0640         *c = value[i];
0641     }
0642 
0643     return NGX_CONF_OK;
0644 }