Annotation of embedaddon/nginx/src/mail/ngx_mail.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 char *ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
                     15: static ngx_int_t ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
                     16:     ngx_mail_listen_t *listen);
                     17: static char *ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports);
                     18: static ngx_int_t ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
                     19:     ngx_mail_conf_addr_t *addr);
                     20: #if (NGX_HAVE_INET6)
                     21: static ngx_int_t ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport,
                     22:     ngx_mail_conf_addr_t *addr);
                     23: #endif
                     24: static ngx_int_t ngx_mail_cmp_conf_addrs(const void *one, const void *two);
                     25: 
                     26: 
                     27: ngx_uint_t  ngx_mail_max_module;
                     28: 
                     29: 
                     30: static ngx_command_t  ngx_mail_commands[] = {
                     31: 
                     32:     { ngx_string("mail"),
                     33:       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
                     34:       ngx_mail_block,
                     35:       0,
                     36:       0,
                     37:       NULL },
                     38: 
                     39:     { ngx_string("imap"),
                     40:       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
                     41:       ngx_mail_block,
                     42:       0,
                     43:       0,
                     44:       NULL },
                     45: 
                     46:       ngx_null_command
                     47: };
                     48: 
                     49: 
                     50: static ngx_core_module_t  ngx_mail_module_ctx = {
                     51:     ngx_string("mail"),
                     52:     NULL,
                     53:     NULL
                     54: };
                     55: 
                     56: 
                     57: ngx_module_t  ngx_mail_module = {
                     58:     NGX_MODULE_V1,
                     59:     &ngx_mail_module_ctx,                  /* module context */
                     60:     ngx_mail_commands,                     /* module directives */
                     61:     NGX_CORE_MODULE,                       /* module type */
                     62:     NULL,                                  /* init master */
                     63:     NULL,                                  /* init module */
                     64:     NULL,                                  /* init process */
                     65:     NULL,                                  /* init thread */
                     66:     NULL,                                  /* exit thread */
                     67:     NULL,                                  /* exit process */
                     68:     NULL,                                  /* exit master */
                     69:     NGX_MODULE_V1_PADDING
                     70: };
                     71: 
                     72: 
                     73: static char *
                     74: ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
                     75: {
                     76:     char                        *rv;
                     77:     ngx_uint_t                   i, m, mi, s;
                     78:     ngx_conf_t                   pcf;
                     79:     ngx_array_t                  ports;
                     80:     ngx_mail_listen_t           *listen;
                     81:     ngx_mail_module_t           *module;
                     82:     ngx_mail_conf_ctx_t         *ctx;
                     83:     ngx_mail_core_srv_conf_t   **cscfp;
                     84:     ngx_mail_core_main_conf_t   *cmcf;
                     85: 
                     86:     if (cmd->name.data[0] == 'i') {
                     87:         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                     88:                            "the \"imap\" directive is deprecated, "
                     89:                            "use the \"mail\" directive instead");
                     90:     }
                     91: 
                     92:     /* the main mail context */
                     93: 
                     94:     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t));
                     95:     if (ctx == NULL) {
                     96:         return NGX_CONF_ERROR;
                     97:     }
                     98: 
                     99:     *(ngx_mail_conf_ctx_t **) conf = ctx;
                    100: 
                    101:     /* count the number of the http modules and set up their indices */
                    102: 
                    103:     ngx_mail_max_module = 0;
                    104:     for (m = 0; ngx_modules[m]; m++) {
                    105:         if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
                    106:             continue;
                    107:         }
                    108: 
                    109:         ngx_modules[m]->ctx_index = ngx_mail_max_module++;
                    110:     }
                    111: 
                    112: 
                    113:     /* the mail main_conf context, it is the same in the all mail contexts */
                    114: 
                    115:     ctx->main_conf = ngx_pcalloc(cf->pool,
                    116:                                  sizeof(void *) * ngx_mail_max_module);
                    117:     if (ctx->main_conf == NULL) {
                    118:         return NGX_CONF_ERROR;
                    119:     }
                    120: 
                    121: 
                    122:     /*
                    123:      * the mail null srv_conf context, it is used to merge
                    124:      * the server{}s' srv_conf's
                    125:      */
                    126: 
                    127:     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module);
                    128:     if (ctx->srv_conf == NULL) {
                    129:         return NGX_CONF_ERROR;
                    130:     }
                    131: 
                    132: 
                    133:     /*
                    134:      * create the main_conf's, the null srv_conf's, and the null loc_conf's
                    135:      * of the all mail modules
                    136:      */
                    137: 
                    138:     for (m = 0; ngx_modules[m]; m++) {
                    139:         if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
                    140:             continue;
                    141:         }
                    142: 
                    143:         module = ngx_modules[m]->ctx;
                    144:         mi = ngx_modules[m]->ctx_index;
                    145: 
                    146:         if (module->create_main_conf) {
                    147:             ctx->main_conf[mi] = module->create_main_conf(cf);
                    148:             if (ctx->main_conf[mi] == NULL) {
                    149:                 return NGX_CONF_ERROR;
                    150:             }
                    151:         }
                    152: 
                    153:         if (module->create_srv_conf) {
                    154:             ctx->srv_conf[mi] = module->create_srv_conf(cf);
                    155:             if (ctx->srv_conf[mi] == NULL) {
                    156:                 return NGX_CONF_ERROR;
                    157:             }
                    158:         }
                    159:     }
                    160: 
                    161: 
                    162:     /* parse inside the mail{} block */
                    163: 
                    164:     pcf = *cf;
                    165:     cf->ctx = ctx;
                    166: 
                    167:     cf->module_type = NGX_MAIL_MODULE;
                    168:     cf->cmd_type = NGX_MAIL_MAIN_CONF;
                    169:     rv = ngx_conf_parse(cf, NULL);
                    170: 
                    171:     if (rv != NGX_CONF_OK) {
                    172:         *cf = pcf;
                    173:         return rv;
                    174:     }
                    175: 
                    176: 
                    177:     /* init mail{} main_conf's, merge the server{}s' srv_conf's */
                    178: 
                    179:     cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index];
                    180:     cscfp = cmcf->servers.elts;
                    181: 
                    182:     for (m = 0; ngx_modules[m]; m++) {
                    183:         if (ngx_modules[m]->type != NGX_MAIL_MODULE) {
                    184:             continue;
                    185:         }
                    186: 
                    187:         module = ngx_modules[m]->ctx;
                    188:         mi = ngx_modules[m]->ctx_index;
                    189: 
                    190:         /* init mail{} main_conf's */
                    191: 
                    192:         cf->ctx = ctx;
                    193: 
                    194:         if (module->init_main_conf) {
                    195:             rv = module->init_main_conf(cf, ctx->main_conf[mi]);
                    196:             if (rv != NGX_CONF_OK) {
                    197:                 *cf = pcf;
                    198:                 return rv;
                    199:             }
                    200:         }
                    201: 
                    202:         for (s = 0; s < cmcf->servers.nelts; s++) {
                    203: 
                    204:             /* merge the server{}s' srv_conf's */
                    205: 
                    206:             cf->ctx = cscfp[s]->ctx;
                    207: 
                    208:             if (module->merge_srv_conf) {
                    209:                 rv = module->merge_srv_conf(cf,
                    210:                                             ctx->srv_conf[mi],
                    211:                                             cscfp[s]->ctx->srv_conf[mi]);
                    212:                 if (rv != NGX_CONF_OK) {
                    213:                     *cf = pcf;
                    214:                     return rv;
                    215:                 }
                    216:             }
                    217:         }
                    218:     }
                    219: 
                    220:     *cf = pcf;
                    221: 
                    222: 
                    223:     if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_mail_conf_port_t))
                    224:         != NGX_OK)
                    225:     {
                    226:         return NGX_CONF_ERROR;
                    227:     }
                    228: 
                    229:     listen = cmcf->listen.elts;
                    230: 
                    231:     for (i = 0; i < cmcf->listen.nelts; i++) {
                    232:         if (ngx_mail_add_ports(cf, &ports, &listen[i]) != NGX_OK) {
                    233:             return NGX_CONF_ERROR;
                    234:         }
                    235:     }
                    236: 
                    237:     return ngx_mail_optimize_servers(cf, &ports);
                    238: }
                    239: 
                    240: 
                    241: static ngx_int_t
                    242: ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
                    243:     ngx_mail_listen_t *listen)
                    244: {
                    245:     in_port_t              p;
                    246:     ngx_uint_t             i;
                    247:     struct sockaddr       *sa;
                    248:     struct sockaddr_in    *sin;
                    249:     ngx_mail_conf_port_t  *port;
                    250:     ngx_mail_conf_addr_t  *addr;
                    251: #if (NGX_HAVE_INET6)
                    252:     struct sockaddr_in6   *sin6;
                    253: #endif
                    254: 
                    255:     sa = (struct sockaddr *) &listen->sockaddr;
                    256: 
                    257:     switch (sa->sa_family) {
                    258: 
                    259: #if (NGX_HAVE_INET6)
                    260:     case AF_INET6:
                    261:         sin6 = (struct sockaddr_in6 *) sa;
                    262:         p = sin6->sin6_port;
                    263:         break;
                    264: #endif
                    265: 
                    266: #if (NGX_HAVE_UNIX_DOMAIN)
                    267:     case AF_UNIX:
                    268:         p = 0;
                    269:         break;
                    270: #endif
                    271: 
                    272:     default: /* AF_INET */
                    273:         sin = (struct sockaddr_in *) sa;
                    274:         p = sin->sin_port;
                    275:         break;
                    276:     }
                    277: 
                    278:     port = ports->elts;
                    279:     for (i = 0; i < ports->nelts; i++) {
                    280:         if (p == port[i].port && sa->sa_family == port[i].family) {
                    281: 
                    282:             /* a port is already in the port list */
                    283: 
                    284:             port = &port[i];
                    285:             goto found;
                    286:         }
                    287:     }
                    288: 
                    289:     /* add a port to the port list */
                    290: 
                    291:     port = ngx_array_push(ports);
                    292:     if (port == NULL) {
                    293:         return NGX_ERROR;
                    294:     }
                    295: 
                    296:     port->family = sa->sa_family;
                    297:     port->port = p;
                    298: 
                    299:     if (ngx_array_init(&port->addrs, cf->temp_pool, 2,
                    300:                        sizeof(ngx_mail_conf_addr_t))
                    301:         != NGX_OK)
                    302:     {
                    303:         return NGX_ERROR;
                    304:     }
                    305: 
                    306: found:
                    307: 
                    308:     addr = ngx_array_push(&port->addrs);
                    309:     if (addr == NULL) {
                    310:         return NGX_ERROR;
                    311:     }
                    312: 
                    313:     addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
                    314:     addr->socklen = listen->socklen;
                    315:     addr->ctx = listen->ctx;
                    316:     addr->bind = listen->bind;
                    317:     addr->wildcard = listen->wildcard;
                    318:     addr->so_keepalive = listen->so_keepalive;
                    319: #if (NGX_HAVE_KEEPALIVE_TUNABLE)
                    320:     addr->tcp_keepidle = listen->tcp_keepidle;
                    321:     addr->tcp_keepintvl = listen->tcp_keepintvl;
                    322:     addr->tcp_keepcnt = listen->tcp_keepcnt;
                    323: #endif
                    324: #if (NGX_MAIL_SSL)
                    325:     addr->ssl = listen->ssl;
                    326: #endif
                    327: #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
                    328:     addr->ipv6only = listen->ipv6only;
                    329: #endif
                    330: 
                    331:     return NGX_OK;
                    332: }
                    333: 
                    334: 
                    335: static char *
                    336: ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
                    337: {
                    338:     ngx_uint_t             i, p, last, bind_wildcard;
                    339:     ngx_listening_t       *ls;
                    340:     ngx_mail_port_t       *mport;
                    341:     ngx_mail_conf_port_t  *port;
                    342:     ngx_mail_conf_addr_t  *addr;
                    343: 
                    344:     port = ports->elts;
                    345:     for (p = 0; p < ports->nelts; p++) {
                    346: 
                    347:         ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
                    348:                  sizeof(ngx_mail_conf_addr_t), ngx_mail_cmp_conf_addrs);
                    349: 
                    350:         addr = port[p].addrs.elts;
                    351:         last = port[p].addrs.nelts;
                    352: 
                    353:         /*
                    354:          * if there is the binding to the "*:port" then we need to bind()
                    355:          * to the "*:port" only and ignore the other bindings
                    356:          */
                    357: 
                    358:         if (addr[last - 1].wildcard) {
                    359:             addr[last - 1].bind = 1;
                    360:             bind_wildcard = 1;
                    361: 
                    362:         } else {
                    363:             bind_wildcard = 0;
                    364:         }
                    365: 
                    366:         i = 0;
                    367: 
                    368:         while (i < last) {
                    369: 
                    370:             if (bind_wildcard && !addr[i].bind) {
                    371:                 i++;
                    372:                 continue;
                    373:             }
                    374: 
                    375:             ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen);
                    376:             if (ls == NULL) {
                    377:                 return NGX_CONF_ERROR;
                    378:             }
                    379: 
                    380:             ls->addr_ntop = 1;
                    381:             ls->handler = ngx_mail_init_connection;
                    382:             ls->pool_size = 256;
                    383: 
                    384:             /* TODO: error_log directive */
                    385:             ls->logp = &cf->cycle->new_log;
                    386:             ls->log.data = &ls->addr_text;
                    387:             ls->log.handler = ngx_accept_log_error;
                    388: 
                    389:             ls->keepalive = addr[i].so_keepalive;
                    390: #if (NGX_HAVE_KEEPALIVE_TUNABLE)
                    391:             ls->keepidle = addr[i].tcp_keepidle;
                    392:             ls->keepintvl = addr[i].tcp_keepintvl;
                    393:             ls->keepcnt = addr[i].tcp_keepcnt;
                    394: #endif
                    395: 
                    396: #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
                    397:             ls->ipv6only = addr[i].ipv6only;
                    398: #endif
                    399: 
                    400:             mport = ngx_palloc(cf->pool, sizeof(ngx_mail_port_t));
                    401:             if (mport == NULL) {
                    402:                 return NGX_CONF_ERROR;
                    403:             }
                    404: 
                    405:             ls->servers = mport;
                    406: 
                    407:             if (i == last - 1) {
                    408:                 mport->naddrs = last;
                    409: 
                    410:             } else {
                    411:                 mport->naddrs = 1;
                    412:                 i = 0;
                    413:             }
                    414: 
                    415:             switch (ls->sockaddr->sa_family) {
                    416: #if (NGX_HAVE_INET6)
                    417:             case AF_INET6:
                    418:                 if (ngx_mail_add_addrs6(cf, mport, addr) != NGX_OK) {
                    419:                     return NGX_CONF_ERROR;
                    420:                 }
                    421:                 break;
                    422: #endif
                    423:             default: /* AF_INET */
                    424:                 if (ngx_mail_add_addrs(cf, mport, addr) != NGX_OK) {
                    425:                     return NGX_CONF_ERROR;
                    426:                 }
                    427:                 break;
                    428:             }
                    429: 
                    430:             addr++;
                    431:             last--;
                    432:         }
                    433:     }
                    434: 
                    435:     return NGX_CONF_OK;
                    436: }
                    437: 
                    438: 
                    439: static ngx_int_t
                    440: ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
                    441:     ngx_mail_conf_addr_t *addr)
                    442: {
                    443:     u_char              *p;
                    444:     size_t               len;
                    445:     ngx_uint_t           i;
                    446:     ngx_mail_in_addr_t  *addrs;
                    447:     struct sockaddr_in  *sin;
                    448:     u_char               buf[NGX_SOCKADDR_STRLEN];
                    449: 
                    450:     mport->addrs = ngx_pcalloc(cf->pool,
                    451:                                mport->naddrs * sizeof(ngx_mail_in_addr_t));
                    452:     if (mport->addrs == NULL) {
                    453:         return NGX_ERROR;
                    454:     }
                    455: 
                    456:     addrs = mport->addrs;
                    457: 
                    458:     for (i = 0; i < mport->naddrs; i++) {
                    459: 
                    460:         sin = (struct sockaddr_in *) addr[i].sockaddr;
                    461:         addrs[i].addr = sin->sin_addr.s_addr;
                    462: 
                    463:         addrs[i].conf.ctx = addr[i].ctx;
                    464: #if (NGX_MAIL_SSL)
                    465:         addrs[i].conf.ssl = addr[i].ssl;
                    466: #endif
                    467: 
                    468:         len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1);
                    469: 
                    470:         p = ngx_pnalloc(cf->pool, len);
                    471:         if (p == NULL) {
                    472:             return NGX_ERROR;
                    473:         }
                    474: 
                    475:         ngx_memcpy(p, buf, len);
                    476: 
                    477:         addrs[i].conf.addr_text.len = len;
                    478:         addrs[i].conf.addr_text.data = p;
                    479:     }
                    480: 
                    481:     return NGX_OK;
                    482: }
                    483: 
                    484: 
                    485: #if (NGX_HAVE_INET6)
                    486: 
                    487: static ngx_int_t
                    488: ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport,
                    489:     ngx_mail_conf_addr_t *addr)
                    490: {
                    491:     u_char               *p;
                    492:     size_t                len;
                    493:     ngx_uint_t            i;
                    494:     ngx_mail_in6_addr_t  *addrs6;
                    495:     struct sockaddr_in6  *sin6;
                    496:     u_char                buf[NGX_SOCKADDR_STRLEN];
                    497: 
                    498:     mport->addrs = ngx_pcalloc(cf->pool,
                    499:                                mport->naddrs * sizeof(ngx_mail_in6_addr_t));
                    500:     if (mport->addrs == NULL) {
                    501:         return NGX_ERROR;
                    502:     }
                    503: 
                    504:     addrs6 = mport->addrs;
                    505: 
                    506:     for (i = 0; i < mport->naddrs; i++) {
                    507: 
                    508:         sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
                    509:         addrs6[i].addr6 = sin6->sin6_addr;
                    510: 
                    511:         addrs6[i].conf.ctx = addr[i].ctx;
                    512: #if (NGX_MAIL_SSL)
                    513:         addrs6[i].conf.ssl = addr[i].ssl;
                    514: #endif
                    515: 
                    516:         len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1);
                    517: 
                    518:         p = ngx_pnalloc(cf->pool, len);
                    519:         if (p == NULL) {
                    520:             return NGX_ERROR;
                    521:         }
                    522: 
                    523:         ngx_memcpy(p, buf, len);
                    524: 
                    525:         addrs6[i].conf.addr_text.len = len;
                    526:         addrs6[i].conf.addr_text.data = p;
                    527:     }
                    528: 
                    529:     return NGX_OK;
                    530: }
                    531: 
                    532: #endif
                    533: 
                    534: 
                    535: static ngx_int_t
                    536: ngx_mail_cmp_conf_addrs(const void *one, const void *two)
                    537: {
                    538:     ngx_mail_conf_addr_t  *first, *second;
                    539: 
                    540:     first = (ngx_mail_conf_addr_t *) one;
                    541:     second = (ngx_mail_conf_addr_t *) two;
                    542: 
                    543:     if (first->wildcard) {
                    544:         /* a wildcard must be the last resort, shift it to the end */
                    545:         return 1;
                    546:     }
                    547: 
                    548:     if (second->wildcard) {
                    549:         /* a wildcard must be the last resort, shift it to the end */
                    550:         return -1;
                    551:     }
                    552: 
                    553:     if (first->bind && !second->bind) {
                    554:         /* shift explicit bind()ed addresses to the start */
                    555:         return -1;
                    556:     }
                    557: 
                    558:     if (!first->bind && second->bind) {
                    559:         /* shift explicit bind()ed addresses to the start */
                    560:         return 1;
                    561:     }
                    562: 
                    563:     /* do not sort by default */
                    564: 
                    565:     return 0;
                    566: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>