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 char *ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
0015 static ngx_int_t ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
0016     ngx_mail_listen_t *listen);
0017 static char *ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports);
0018 static ngx_int_t ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
0019     ngx_mail_conf_addr_t *addr);
0020 #if (NGX_HAVE_INET6)
0021 static ngx_int_t ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport,
0022     ngx_mail_conf_addr_t *addr);
0023 #endif
0024 static ngx_int_t ngx_mail_cmp_conf_addrs(const void *one, const void *two);
0025 
0026 
0027 ngx_uint_t  ngx_mail_max_module;
0028 
0029 
0030 static ngx_command_t  ngx_mail_commands[] = {
0031 
0032     { ngx_string("mail"),
0033       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
0034       ngx_mail_block,
0035       0,
0036       0,
0037       NULL },
0038 
0039       ngx_null_command
0040 };
0041 
0042 
0043 static ngx_core_module_t  ngx_mail_module_ctx = {
0044     ngx_string("mail"),
0045     NULL,
0046     NULL
0047 };
0048 
0049 
0050 ngx_module_t  ngx_mail_module = {
0051     NGX_MODULE_V1,
0052     &ngx_mail_module_ctx,                  /* module context */
0053     ngx_mail_commands,                     /* module directives */
0054     NGX_CORE_MODULE,                       /* module type */
0055     NULL,                                  /* init master */
0056     NULL,                                  /* init module */
0057     NULL,                                  /* init process */
0058     NULL,                                  /* init thread */
0059     NULL,                                  /* exit thread */
0060     NULL,                                  /* exit process */
0061     NULL,                                  /* exit master */
0062     NGX_MODULE_V1_PADDING
0063 };
0064 
0065 
0066 static char *
0067 ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0068 {
0069     char                        *rv;
0070     ngx_uint_t                   i, m, mi, s;
0071     ngx_conf_t                   pcf;
0072     ngx_array_t                  ports;
0073     ngx_mail_listen_t           *listen;
0074     ngx_mail_module_t           *module;
0075     ngx_mail_conf_ctx_t         *ctx;
0076     ngx_mail_core_srv_conf_t   **cscfp;
0077     ngx_mail_core_main_conf_t   *cmcf;
0078 
0079     if (*(ngx_mail_conf_ctx_t **) conf) {
0080         return "is duplicate";
0081     }
0082 
0083     /* the main mail context */
0084 
0085     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t));
0086     if (ctx == NULL) {
0087         return NGX_CONF_ERROR;
0088     }
0089 
0090     *(ngx_mail_conf_ctx_t **) conf = ctx;
0091 
0092     /* count the number of the mail modules and set up their indices */
0093 
0094     ngx_mail_max_module = ngx_count_modules(cf->cycle, NGX_MAIL_MODULE);
0095 
0096 
0097     /* the mail main_conf context, it is the same in the all mail contexts */
0098 
0099     ctx->main_conf = ngx_pcalloc(cf->pool,
0100                                  sizeof(void *) * ngx_mail_max_module);
0101     if (ctx->main_conf == NULL) {
0102         return NGX_CONF_ERROR;
0103     }
0104 
0105 
0106     /*
0107      * the mail null srv_conf context, it is used to merge
0108      * the server{}s' srv_conf's
0109      */
0110 
0111     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module);
0112     if (ctx->srv_conf == NULL) {
0113         return NGX_CONF_ERROR;
0114     }
0115 
0116 
0117     /*
0118      * create the main_conf's and the null srv_conf's of the all mail modules
0119      */
0120 
0121     for (m = 0; cf->cycle->modules[m]; m++) {
0122         if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) {
0123             continue;
0124         }
0125 
0126         module = cf->cycle->modules[m]->ctx;
0127         mi = cf->cycle->modules[m]->ctx_index;
0128 
0129         if (module->create_main_conf) {
0130             ctx->main_conf[mi] = module->create_main_conf(cf);
0131             if (ctx->main_conf[mi] == NULL) {
0132                 return NGX_CONF_ERROR;
0133             }
0134         }
0135 
0136         if (module->create_srv_conf) {
0137             ctx->srv_conf[mi] = module->create_srv_conf(cf);
0138             if (ctx->srv_conf[mi] == NULL) {
0139                 return NGX_CONF_ERROR;
0140             }
0141         }
0142     }
0143 
0144 
0145     /* parse inside the mail{} block */
0146 
0147     pcf = *cf;
0148     cf->ctx = ctx;
0149 
0150     cf->module_type = NGX_MAIL_MODULE;
0151     cf->cmd_type = NGX_MAIL_MAIN_CONF;
0152     rv = ngx_conf_parse(cf, NULL);
0153 
0154     if (rv != NGX_CONF_OK) {
0155         *cf = pcf;
0156         return rv;
0157     }
0158 
0159 
0160     /* init mail{} main_conf's, merge the server{}s' srv_conf's */
0161 
0162     cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index];
0163     cscfp = cmcf->servers.elts;
0164 
0165     for (m = 0; cf->cycle->modules[m]; m++) {
0166         if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) {
0167             continue;
0168         }
0169 
0170         module = cf->cycle->modules[m]->ctx;
0171         mi = cf->cycle->modules[m]->ctx_index;
0172 
0173         /* init mail{} main_conf's */
0174 
0175         cf->ctx = ctx;
0176 
0177         if (module->init_main_conf) {
0178             rv = module->init_main_conf(cf, ctx->main_conf[mi]);
0179             if (rv != NGX_CONF_OK) {
0180                 *cf = pcf;
0181                 return rv;
0182             }
0183         }
0184 
0185         for (s = 0; s < cmcf->servers.nelts; s++) {
0186 
0187             /* merge the server{}s' srv_conf's */
0188 
0189             cf->ctx = cscfp[s]->ctx;
0190 
0191             if (module->merge_srv_conf) {
0192                 rv = module->merge_srv_conf(cf,
0193                                             ctx->srv_conf[mi],
0194                                             cscfp[s]->ctx->srv_conf[mi]);
0195                 if (rv != NGX_CONF_OK) {
0196                     *cf = pcf;
0197                     return rv;
0198                 }
0199             }
0200         }
0201     }
0202 
0203     *cf = pcf;
0204 
0205 
0206     if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_mail_conf_port_t))
0207         != NGX_OK)
0208     {
0209         return NGX_CONF_ERROR;
0210     }
0211 
0212     listen = cmcf->listen.elts;
0213 
0214     for (i = 0; i < cmcf->listen.nelts; i++) {
0215         if (ngx_mail_add_ports(cf, &ports, &listen[i]) != NGX_OK) {
0216             return NGX_CONF_ERROR;
0217         }
0218     }
0219 
0220     return ngx_mail_optimize_servers(cf, &ports);
0221 }
0222 
0223 
0224 static ngx_int_t
0225 ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
0226     ngx_mail_listen_t *listen)
0227 {
0228     in_port_t              p;
0229     ngx_uint_t             i;
0230     struct sockaddr       *sa;
0231     ngx_mail_conf_port_t  *port;
0232     ngx_mail_conf_addr_t  *addr;
0233 
0234     sa = &listen->sockaddr.sockaddr;
0235     p = ngx_inet_get_port(sa);
0236 
0237     port = ports->elts;
0238     for (i = 0; i < ports->nelts; i++) {
0239         if (p == port[i].port && sa->sa_family == port[i].family) {
0240 
0241             /* a port is already in the port list */
0242 
0243             port = &port[i];
0244             goto found;
0245         }
0246     }
0247 
0248     /* add a port to the port list */
0249 
0250     port = ngx_array_push(ports);
0251     if (port == NULL) {
0252         return NGX_ERROR;
0253     }
0254 
0255     port->family = sa->sa_family;
0256     port->port = p;
0257 
0258     if (ngx_array_init(&port->addrs, cf->temp_pool, 2,
0259                        sizeof(ngx_mail_conf_addr_t))
0260         != NGX_OK)
0261     {
0262         return NGX_ERROR;
0263     }
0264 
0265 found:
0266 
0267     addr = ngx_array_push(&port->addrs);
0268     if (addr == NULL) {
0269         return NGX_ERROR;
0270     }
0271 
0272     addr->opt = *listen;
0273 
0274     return NGX_OK;
0275 }
0276 
0277 
0278 static char *
0279 ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
0280 {
0281     ngx_uint_t                 i, p, last, bind_wildcard;
0282     ngx_listening_t           *ls;
0283     ngx_mail_port_t           *mport;
0284     ngx_mail_conf_port_t      *port;
0285     ngx_mail_conf_addr_t      *addr;
0286     ngx_mail_core_srv_conf_t  *cscf;
0287 
0288     port = ports->elts;
0289     for (p = 0; p < ports->nelts; p++) {
0290 
0291         ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
0292                  sizeof(ngx_mail_conf_addr_t), ngx_mail_cmp_conf_addrs);
0293 
0294         addr = port[p].addrs.elts;
0295         last = port[p].addrs.nelts;
0296 
0297         /*
0298          * if there is the binding to the "*:port" then we need to bind()
0299          * to the "*:port" only and ignore the other bindings
0300          */
0301 
0302         if (addr[last - 1].opt.wildcard) {
0303             addr[last - 1].opt.bind = 1;
0304             bind_wildcard = 1;
0305 
0306         } else {
0307             bind_wildcard = 0;
0308         }
0309 
0310         i = 0;
0311 
0312         while (i < last) {
0313 
0314             if (bind_wildcard && !addr[i].opt.bind) {
0315                 i++;
0316                 continue;
0317             }
0318 
0319             ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr,
0320                                       addr[i].opt.socklen);
0321             if (ls == NULL) {
0322                 return NGX_CONF_ERROR;
0323             }
0324 
0325             ls->addr_ntop = 1;
0326             ls->handler = ngx_mail_init_connection;
0327             ls->pool_size = 256;
0328 
0329             cscf = addr->opt.ctx->srv_conf[ngx_mail_core_module.ctx_index];
0330 
0331             ls->logp = cscf->error_log;
0332             ls->log.data = &ls->addr_text;
0333             ls->log.handler = ngx_accept_log_error;
0334 
0335             ls->backlog = addr[i].opt.backlog;
0336             ls->rcvbuf = addr[i].opt.rcvbuf;
0337             ls->sndbuf = addr[i].opt.sndbuf;
0338 
0339             ls->keepalive = addr[i].opt.so_keepalive;
0340 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0341             ls->keepidle = addr[i].opt.tcp_keepidle;
0342             ls->keepintvl = addr[i].opt.tcp_keepintvl;
0343             ls->keepcnt = addr[i].opt.tcp_keepcnt;
0344 #endif
0345 
0346 #if (NGX_HAVE_INET6)
0347             ls->ipv6only = addr[i].opt.ipv6only;
0348 #endif
0349 
0350             mport = ngx_palloc(cf->pool, sizeof(ngx_mail_port_t));
0351             if (mport == NULL) {
0352                 return NGX_CONF_ERROR;
0353             }
0354 
0355             ls->servers = mport;
0356 
0357             mport->naddrs = i + 1;
0358 
0359             switch (ls->sockaddr->sa_family) {
0360 #if (NGX_HAVE_INET6)
0361             case AF_INET6:
0362                 if (ngx_mail_add_addrs6(cf, mport, addr) != NGX_OK) {
0363                     return NGX_CONF_ERROR;
0364                 }
0365                 break;
0366 #endif
0367             default: /* AF_INET */
0368                 if (ngx_mail_add_addrs(cf, mport, addr) != NGX_OK) {
0369                     return NGX_CONF_ERROR;
0370                 }
0371                 break;
0372             }
0373 
0374             addr++;
0375             last--;
0376         }
0377     }
0378 
0379     return NGX_CONF_OK;
0380 }
0381 
0382 
0383 static ngx_int_t
0384 ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
0385     ngx_mail_conf_addr_t *addr)
0386 {
0387     u_char              *p;
0388     size_t               len;
0389     ngx_uint_t           i;
0390     ngx_mail_in_addr_t  *addrs;
0391     struct sockaddr_in  *sin;
0392     u_char               buf[NGX_SOCKADDR_STRLEN];
0393 
0394     mport->addrs = ngx_pcalloc(cf->pool,
0395                                mport->naddrs * sizeof(ngx_mail_in_addr_t));
0396     if (mport->addrs == NULL) {
0397         return NGX_ERROR;
0398     }
0399 
0400     addrs = mport->addrs;
0401 
0402     for (i = 0; i < mport->naddrs; i++) {
0403 
0404         sin = &addr[i].opt.sockaddr.sockaddr_in;
0405         addrs[i].addr = sin->sin_addr.s_addr;
0406 
0407         addrs[i].conf.ctx = addr[i].opt.ctx;
0408 #if (NGX_MAIL_SSL)
0409         addrs[i].conf.ssl = addr[i].opt.ssl;
0410 #endif
0411 
0412         len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen,
0413                             buf, NGX_SOCKADDR_STRLEN, 1);
0414 
0415         p = ngx_pnalloc(cf->pool, len);
0416         if (p == NULL) {
0417             return NGX_ERROR;
0418         }
0419 
0420         ngx_memcpy(p, buf, len);
0421 
0422         addrs[i].conf.addr_text.len = len;
0423         addrs[i].conf.addr_text.data = p;
0424     }
0425 
0426     return NGX_OK;
0427 }
0428 
0429 
0430 #if (NGX_HAVE_INET6)
0431 
0432 static ngx_int_t
0433 ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport,
0434     ngx_mail_conf_addr_t *addr)
0435 {
0436     u_char               *p;
0437     size_t                len;
0438     ngx_uint_t            i;
0439     ngx_mail_in6_addr_t  *addrs6;
0440     struct sockaddr_in6  *sin6;
0441     u_char                buf[NGX_SOCKADDR_STRLEN];
0442 
0443     mport->addrs = ngx_pcalloc(cf->pool,
0444                                mport->naddrs * sizeof(ngx_mail_in6_addr_t));
0445     if (mport->addrs == NULL) {
0446         return NGX_ERROR;
0447     }
0448 
0449     addrs6 = mport->addrs;
0450 
0451     for (i = 0; i < mport->naddrs; i++) {
0452 
0453         sin6 = &addr[i].opt.sockaddr.sockaddr_in6;
0454         addrs6[i].addr6 = sin6->sin6_addr;
0455 
0456         addrs6[i].conf.ctx = addr[i].opt.ctx;
0457 #if (NGX_MAIL_SSL)
0458         addrs6[i].conf.ssl = addr[i].opt.ssl;
0459 #endif
0460 
0461         len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen,
0462                             buf, NGX_SOCKADDR_STRLEN, 1);
0463 
0464         p = ngx_pnalloc(cf->pool, len);
0465         if (p == NULL) {
0466             return NGX_ERROR;
0467         }
0468 
0469         ngx_memcpy(p, buf, len);
0470 
0471         addrs6[i].conf.addr_text.len = len;
0472         addrs6[i].conf.addr_text.data = p;
0473     }
0474 
0475     return NGX_OK;
0476 }
0477 
0478 #endif
0479 
0480 
0481 static ngx_int_t
0482 ngx_mail_cmp_conf_addrs(const void *one, const void *two)
0483 {
0484     ngx_mail_conf_addr_t  *first, *second;
0485 
0486     first = (ngx_mail_conf_addr_t *) one;
0487     second = (ngx_mail_conf_addr_t *) two;
0488 
0489     if (first->opt.wildcard) {
0490         /* a wildcard must be the last resort, shift it to the end */
0491         return 1;
0492     }
0493 
0494     if (second->opt.wildcard) {
0495         /* a wildcard must be the last resort, shift it to the end */
0496         return -1;
0497     }
0498 
0499     if (first->opt.bind && !second->opt.bind) {
0500         /* shift explicit bind()ed addresses to the start */
0501         return -1;
0502     }
0503 
0504     if (!first->opt.bind && second->opt.bind) {
0505         /* shift explicit bind()ed addresses to the start */
0506         return 1;
0507     }
0508 
0509     /* do not sort by default */
0510 
0511     return 0;
0512 }