Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

0001 
0002 /*
0003  * Copyright (C) Roman Arutyunyan
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_stream.h>
0012 
0013 
0014 static char *ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
0015 static ngx_int_t ngx_stream_init_phases(ngx_conf_t *cf,
0016     ngx_stream_core_main_conf_t *cmcf);
0017 static ngx_int_t ngx_stream_init_phase_handlers(ngx_conf_t *cf,
0018     ngx_stream_core_main_conf_t *cmcf);
0019 static ngx_int_t ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
0020     ngx_stream_listen_t *listen);
0021 static char *ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports);
0022 static ngx_int_t ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport,
0023     ngx_stream_conf_addr_t *addr);
0024 #if (NGX_HAVE_INET6)
0025 static ngx_int_t ngx_stream_add_addrs6(ngx_conf_t *cf,
0026     ngx_stream_port_t *stport, ngx_stream_conf_addr_t *addr);
0027 #endif
0028 static ngx_int_t ngx_stream_cmp_conf_addrs(const void *one, const void *two);
0029 
0030 
0031 ngx_uint_t  ngx_stream_max_module;
0032 
0033 
0034 ngx_stream_filter_pt  ngx_stream_top_filter;
0035 
0036 
0037 static ngx_command_t  ngx_stream_commands[] = {
0038 
0039     { ngx_string("stream"),
0040       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
0041       ngx_stream_block,
0042       0,
0043       0,
0044       NULL },
0045 
0046       ngx_null_command
0047 };
0048 
0049 
0050 static ngx_core_module_t  ngx_stream_module_ctx = {
0051     ngx_string("stream"),
0052     NULL,
0053     NULL
0054 };
0055 
0056 
0057 ngx_module_t  ngx_stream_module = {
0058     NGX_MODULE_V1,
0059     &ngx_stream_module_ctx,                /* module context */
0060     ngx_stream_commands,                   /* module directives */
0061     NGX_CORE_MODULE,                       /* module type */
0062     NULL,                                  /* init master */
0063     NULL,                                  /* init module */
0064     NULL,                                  /* init process */
0065     NULL,                                  /* init thread */
0066     NULL,                                  /* exit thread */
0067     NULL,                                  /* exit process */
0068     NULL,                                  /* exit master */
0069     NGX_MODULE_V1_PADDING
0070 };
0071 
0072 
0073 static char *
0074 ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0075 {
0076     char                          *rv;
0077     ngx_uint_t                     i, m, mi, s;
0078     ngx_conf_t                     pcf;
0079     ngx_array_t                    ports;
0080     ngx_stream_listen_t           *listen;
0081     ngx_stream_module_t           *module;
0082     ngx_stream_conf_ctx_t         *ctx;
0083     ngx_stream_core_srv_conf_t   **cscfp;
0084     ngx_stream_core_main_conf_t   *cmcf;
0085 
0086     if (*(ngx_stream_conf_ctx_t **) conf) {
0087         return "is duplicate";
0088     }
0089 
0090     /* the main stream context */
0091 
0092     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t));
0093     if (ctx == NULL) {
0094         return NGX_CONF_ERROR;
0095     }
0096 
0097     *(ngx_stream_conf_ctx_t **) conf = ctx;
0098 
0099     /* count the number of the stream modules and set up their indices */
0100 
0101     ngx_stream_max_module = ngx_count_modules(cf->cycle, NGX_STREAM_MODULE);
0102 
0103 
0104     /* the stream main_conf context, it's the same in the all stream contexts */
0105 
0106     ctx->main_conf = ngx_pcalloc(cf->pool,
0107                                  sizeof(void *) * ngx_stream_max_module);
0108     if (ctx->main_conf == NULL) {
0109         return NGX_CONF_ERROR;
0110     }
0111 
0112 
0113     /*
0114      * the stream null srv_conf context, it is used to merge
0115      * the server{}s' srv_conf's
0116      */
0117 
0118     ctx->srv_conf = ngx_pcalloc(cf->pool,
0119                                 sizeof(void *) * ngx_stream_max_module);
0120     if (ctx->srv_conf == NULL) {
0121         return NGX_CONF_ERROR;
0122     }
0123 
0124 
0125     /*
0126      * create the main_conf's and the null srv_conf's of the all stream modules
0127      */
0128 
0129     for (m = 0; cf->cycle->modules[m]; m++) {
0130         if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) {
0131             continue;
0132         }
0133 
0134         module = cf->cycle->modules[m]->ctx;
0135         mi = cf->cycle->modules[m]->ctx_index;
0136 
0137         if (module->create_main_conf) {
0138             ctx->main_conf[mi] = module->create_main_conf(cf);
0139             if (ctx->main_conf[mi] == NULL) {
0140                 return NGX_CONF_ERROR;
0141             }
0142         }
0143 
0144         if (module->create_srv_conf) {
0145             ctx->srv_conf[mi] = module->create_srv_conf(cf);
0146             if (ctx->srv_conf[mi] == NULL) {
0147                 return NGX_CONF_ERROR;
0148             }
0149         }
0150     }
0151 
0152 
0153     pcf = *cf;
0154     cf->ctx = ctx;
0155 
0156     for (m = 0; cf->cycle->modules[m]; m++) {
0157         if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) {
0158             continue;
0159         }
0160 
0161         module = cf->cycle->modules[m]->ctx;
0162 
0163         if (module->preconfiguration) {
0164             if (module->preconfiguration(cf) != NGX_OK) {
0165                 return NGX_CONF_ERROR;
0166             }
0167         }
0168     }
0169 
0170 
0171     /* parse inside the stream{} block */
0172 
0173     cf->module_type = NGX_STREAM_MODULE;
0174     cf->cmd_type = NGX_STREAM_MAIN_CONF;
0175     rv = ngx_conf_parse(cf, NULL);
0176 
0177     if (rv != NGX_CONF_OK) {
0178         *cf = pcf;
0179         return rv;
0180     }
0181 
0182 
0183     /* init stream{} main_conf's, merge the server{}s' srv_conf's */
0184 
0185     cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index];
0186     cscfp = cmcf->servers.elts;
0187 
0188     for (m = 0; cf->cycle->modules[m]; m++) {
0189         if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) {
0190             continue;
0191         }
0192 
0193         module = cf->cycle->modules[m]->ctx;
0194         mi = cf->cycle->modules[m]->ctx_index;
0195 
0196         /* init stream{} main_conf's */
0197 
0198         cf->ctx = ctx;
0199 
0200         if (module->init_main_conf) {
0201             rv = module->init_main_conf(cf, ctx->main_conf[mi]);
0202             if (rv != NGX_CONF_OK) {
0203                 *cf = pcf;
0204                 return rv;
0205             }
0206         }
0207 
0208         for (s = 0; s < cmcf->servers.nelts; s++) {
0209 
0210             /* merge the server{}s' srv_conf's */
0211 
0212             cf->ctx = cscfp[s]->ctx;
0213 
0214             if (module->merge_srv_conf) {
0215                 rv = module->merge_srv_conf(cf,
0216                                             ctx->srv_conf[mi],
0217                                             cscfp[s]->ctx->srv_conf[mi]);
0218                 if (rv != NGX_CONF_OK) {
0219                     *cf = pcf;
0220                     return rv;
0221                 }
0222             }
0223         }
0224     }
0225 
0226     if (ngx_stream_init_phases(cf, cmcf) != NGX_OK) {
0227         return NGX_CONF_ERROR;
0228     }
0229 
0230     for (m = 0; cf->cycle->modules[m]; m++) {
0231         if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) {
0232             continue;
0233         }
0234 
0235         module = cf->cycle->modules[m]->ctx;
0236 
0237         if (module->postconfiguration) {
0238             if (module->postconfiguration(cf) != NGX_OK) {
0239                 return NGX_CONF_ERROR;
0240             }
0241         }
0242     }
0243 
0244     if (ngx_stream_variables_init_vars(cf) != NGX_OK) {
0245         return NGX_CONF_ERROR;
0246     }
0247 
0248     *cf = pcf;
0249 
0250     if (ngx_stream_init_phase_handlers(cf, cmcf) != NGX_OK) {
0251         return NGX_CONF_ERROR;
0252     }
0253 
0254     if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_stream_conf_port_t))
0255         != NGX_OK)
0256     {
0257         return NGX_CONF_ERROR;
0258     }
0259 
0260     listen = cmcf->listen.elts;
0261 
0262     for (i = 0; i < cmcf->listen.nelts; i++) {
0263         if (ngx_stream_add_ports(cf, &ports, &listen[i]) != NGX_OK) {
0264             return NGX_CONF_ERROR;
0265         }
0266     }
0267 
0268     return ngx_stream_optimize_servers(cf, &ports);
0269 }
0270 
0271 
0272 static ngx_int_t
0273 ngx_stream_init_phases(ngx_conf_t *cf, ngx_stream_core_main_conf_t *cmcf)
0274 {
0275     if (ngx_array_init(&cmcf->phases[NGX_STREAM_POST_ACCEPT_PHASE].handlers,
0276                        cf->pool, 1, sizeof(ngx_stream_handler_pt))
0277         != NGX_OK)
0278     {
0279         return NGX_ERROR;
0280     }
0281 
0282     if (ngx_array_init(&cmcf->phases[NGX_STREAM_PREACCESS_PHASE].handlers,
0283                        cf->pool, 1, sizeof(ngx_stream_handler_pt))
0284         != NGX_OK)
0285     {
0286         return NGX_ERROR;
0287     }
0288 
0289     if (ngx_array_init(&cmcf->phases[NGX_STREAM_ACCESS_PHASE].handlers,
0290                        cf->pool, 1, sizeof(ngx_stream_handler_pt))
0291         != NGX_OK)
0292     {
0293         return NGX_ERROR;
0294     }
0295 
0296     if (ngx_array_init(&cmcf->phases[NGX_STREAM_SSL_PHASE].handlers,
0297                        cf->pool, 1, sizeof(ngx_stream_handler_pt))
0298         != NGX_OK)
0299     {
0300         return NGX_ERROR;
0301     }
0302 
0303     if (ngx_array_init(&cmcf->phases[NGX_STREAM_PREREAD_PHASE].handlers,
0304                        cf->pool, 1, sizeof(ngx_stream_handler_pt))
0305         != NGX_OK)
0306     {
0307         return NGX_ERROR;
0308     }
0309 
0310     if (ngx_array_init(&cmcf->phases[NGX_STREAM_LOG_PHASE].handlers,
0311                        cf->pool, 1, sizeof(ngx_stream_handler_pt))
0312         != NGX_OK)
0313     {
0314         return NGX_ERROR;
0315     }
0316 
0317     return NGX_OK;
0318 }
0319 
0320 
0321 static ngx_int_t
0322 ngx_stream_init_phase_handlers(ngx_conf_t *cf,
0323     ngx_stream_core_main_conf_t *cmcf)
0324 {
0325     ngx_int_t                     j;
0326     ngx_uint_t                    i, n;
0327     ngx_stream_handler_pt        *h;
0328     ngx_stream_phase_handler_t   *ph;
0329     ngx_stream_phase_handler_pt   checker;
0330 
0331     n = 1 /* content phase */;
0332 
0333     for (i = 0; i < NGX_STREAM_LOG_PHASE; i++) {
0334         n += cmcf->phases[i].handlers.nelts;
0335     }
0336 
0337     ph = ngx_pcalloc(cf->pool,
0338                      n * sizeof(ngx_stream_phase_handler_t) + sizeof(void *));
0339     if (ph == NULL) {
0340         return NGX_ERROR;
0341     }
0342 
0343     cmcf->phase_engine.handlers = ph;
0344     n = 0;
0345 
0346     for (i = 0; i < NGX_STREAM_LOG_PHASE; i++) {
0347         h = cmcf->phases[i].handlers.elts;
0348 
0349         switch (i) {
0350 
0351         case NGX_STREAM_PREREAD_PHASE:
0352             checker = ngx_stream_core_preread_phase;
0353             break;
0354 
0355         case NGX_STREAM_CONTENT_PHASE:
0356             ph->checker = ngx_stream_core_content_phase;
0357             n++;
0358             ph++;
0359 
0360             continue;
0361 
0362         default:
0363             checker = ngx_stream_core_generic_phase;
0364         }
0365 
0366         n += cmcf->phases[i].handlers.nelts;
0367 
0368         for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) {
0369             ph->checker = checker;
0370             ph->handler = h[j];
0371             ph->next = n;
0372             ph++;
0373         }
0374     }
0375 
0376     return NGX_OK;
0377 }
0378 
0379 
0380 static ngx_int_t
0381 ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
0382     ngx_stream_listen_t *listen)
0383 {
0384     in_port_t                p;
0385     ngx_uint_t               i;
0386     struct sockaddr         *sa;
0387     ngx_stream_conf_port_t  *port;
0388     ngx_stream_conf_addr_t  *addr;
0389 
0390     sa = listen->sockaddr;
0391     p = ngx_inet_get_port(sa);
0392 
0393     port = ports->elts;
0394     for (i = 0; i < ports->nelts; i++) {
0395 
0396         if (p == port[i].port
0397             && listen->type == port[i].type
0398             && sa->sa_family == port[i].family)
0399         {
0400             /* a port is already in the port list */
0401 
0402             port = &port[i];
0403             goto found;
0404         }
0405     }
0406 
0407     /* add a port to the port list */
0408 
0409     port = ngx_array_push(ports);
0410     if (port == NULL) {
0411         return NGX_ERROR;
0412     }
0413 
0414     port->family = sa->sa_family;
0415     port->type = listen->type;
0416     port->port = p;
0417 
0418     if (ngx_array_init(&port->addrs, cf->temp_pool, 2,
0419                        sizeof(ngx_stream_conf_addr_t))
0420         != NGX_OK)
0421     {
0422         return NGX_ERROR;
0423     }
0424 
0425 found:
0426 
0427     addr = ngx_array_push(&port->addrs);
0428     if (addr == NULL) {
0429         return NGX_ERROR;
0430     }
0431 
0432     addr->opt = *listen;
0433 
0434     return NGX_OK;
0435 }
0436 
0437 
0438 static char *
0439 ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
0440 {
0441     ngx_uint_t                   i, p, last, bind_wildcard;
0442     ngx_listening_t             *ls;
0443     ngx_stream_port_t           *stport;
0444     ngx_stream_conf_port_t      *port;
0445     ngx_stream_conf_addr_t      *addr;
0446     ngx_stream_core_srv_conf_t  *cscf;
0447 
0448     port = ports->elts;
0449     for (p = 0; p < ports->nelts; p++) {
0450 
0451         ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
0452                  sizeof(ngx_stream_conf_addr_t), ngx_stream_cmp_conf_addrs);
0453 
0454         addr = port[p].addrs.elts;
0455         last = port[p].addrs.nelts;
0456 
0457         /*
0458          * if there is the binding to the "*:port" then we need to bind()
0459          * to the "*:port" only and ignore the other bindings
0460          */
0461 
0462         if (addr[last - 1].opt.wildcard) {
0463             addr[last - 1].opt.bind = 1;
0464             bind_wildcard = 1;
0465 
0466         } else {
0467             bind_wildcard = 0;
0468         }
0469 
0470         i = 0;
0471 
0472         while (i < last) {
0473 
0474             if (bind_wildcard && !addr[i].opt.bind) {
0475                 i++;
0476                 continue;
0477             }
0478 
0479             ls = ngx_create_listening(cf, addr[i].opt.sockaddr,
0480                                       addr[i].opt.socklen);
0481             if (ls == NULL) {
0482                 return NGX_CONF_ERROR;
0483             }
0484 
0485             ls->addr_ntop = 1;
0486             ls->handler = ngx_stream_init_connection;
0487             ls->pool_size = 256;
0488             ls->type = addr[i].opt.type;
0489 
0490             cscf = addr->opt.ctx->srv_conf[ngx_stream_core_module.ctx_index];
0491 
0492             ls->logp = cscf->error_log;
0493             ls->log.data = &ls->addr_text;
0494             ls->log.handler = ngx_accept_log_error;
0495 
0496             ls->backlog = addr[i].opt.backlog;
0497             ls->rcvbuf = addr[i].opt.rcvbuf;
0498             ls->sndbuf = addr[i].opt.sndbuf;
0499 
0500             ls->wildcard = addr[i].opt.wildcard;
0501 
0502             ls->keepalive = addr[i].opt.so_keepalive;
0503 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0504             ls->keepidle = addr[i].opt.tcp_keepidle;
0505             ls->keepintvl = addr[i].opt.tcp_keepintvl;
0506             ls->keepcnt = addr[i].opt.tcp_keepcnt;
0507 #endif
0508 
0509 #if (NGX_HAVE_INET6)
0510             ls->ipv6only = addr[i].opt.ipv6only;
0511 #endif
0512 
0513 #if (NGX_HAVE_REUSEPORT)
0514             ls->reuseport = addr[i].opt.reuseport;
0515 #endif
0516 
0517             stport = ngx_palloc(cf->pool, sizeof(ngx_stream_port_t));
0518             if (stport == NULL) {
0519                 return NGX_CONF_ERROR;
0520             }
0521 
0522             ls->servers = stport;
0523 
0524             stport->naddrs = i + 1;
0525 
0526             switch (ls->sockaddr->sa_family) {
0527 #if (NGX_HAVE_INET6)
0528             case AF_INET6:
0529                 if (ngx_stream_add_addrs6(cf, stport, addr) != NGX_OK) {
0530                     return NGX_CONF_ERROR;
0531                 }
0532                 break;
0533 #endif
0534             default: /* AF_INET */
0535                 if (ngx_stream_add_addrs(cf, stport, addr) != NGX_OK) {
0536                     return NGX_CONF_ERROR;
0537                 }
0538                 break;
0539             }
0540 
0541             addr++;
0542             last--;
0543         }
0544     }
0545 
0546     return NGX_CONF_OK;
0547 }
0548 
0549 
0550 static ngx_int_t
0551 ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport,
0552     ngx_stream_conf_addr_t *addr)
0553 {
0554     ngx_uint_t             i;
0555     struct sockaddr_in    *sin;
0556     ngx_stream_in_addr_t  *addrs;
0557 
0558     stport->addrs = ngx_pcalloc(cf->pool,
0559                                 stport->naddrs * sizeof(ngx_stream_in_addr_t));
0560     if (stport->addrs == NULL) {
0561         return NGX_ERROR;
0562     }
0563 
0564     addrs = stport->addrs;
0565 
0566     for (i = 0; i < stport->naddrs; i++) {
0567 
0568         sin = (struct sockaddr_in *) addr[i].opt.sockaddr;
0569         addrs[i].addr = sin->sin_addr.s_addr;
0570 
0571         addrs[i].conf.ctx = addr[i].opt.ctx;
0572 #if (NGX_STREAM_SSL)
0573         addrs[i].conf.ssl = addr[i].opt.ssl;
0574 #endif
0575         addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
0576         addrs[i].conf.addr_text = addr[i].opt.addr_text;
0577     }
0578 
0579     return NGX_OK;
0580 }
0581 
0582 
0583 #if (NGX_HAVE_INET6)
0584 
0585 static ngx_int_t
0586 ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport,
0587     ngx_stream_conf_addr_t *addr)
0588 {
0589     ngx_uint_t              i;
0590     struct sockaddr_in6    *sin6;
0591     ngx_stream_in6_addr_t  *addrs6;
0592 
0593     stport->addrs = ngx_pcalloc(cf->pool,
0594                                 stport->naddrs * sizeof(ngx_stream_in6_addr_t));
0595     if (stport->addrs == NULL) {
0596         return NGX_ERROR;
0597     }
0598 
0599     addrs6 = stport->addrs;
0600 
0601     for (i = 0; i < stport->naddrs; i++) {
0602 
0603         sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr;
0604         addrs6[i].addr6 = sin6->sin6_addr;
0605 
0606         addrs6[i].conf.ctx = addr[i].opt.ctx;
0607 #if (NGX_STREAM_SSL)
0608         addrs6[i].conf.ssl = addr[i].opt.ssl;
0609 #endif
0610         addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
0611         addrs6[i].conf.addr_text = addr[i].opt.addr_text;
0612     }
0613 
0614     return NGX_OK;
0615 }
0616 
0617 #endif
0618 
0619 
0620 static ngx_int_t
0621 ngx_stream_cmp_conf_addrs(const void *one, const void *two)
0622 {
0623     ngx_stream_conf_addr_t  *first, *second;
0624 
0625     first = (ngx_stream_conf_addr_t *) one;
0626     second = (ngx_stream_conf_addr_t *) two;
0627 
0628     if (first->opt.wildcard) {
0629         /* a wildcard must be the last resort, shift it to the end */
0630         return 1;
0631     }
0632 
0633     if (second->opt.wildcard) {
0634         /* a wildcard must be the last resort, shift it to the end */
0635         return -1;
0636     }
0637 
0638     if (first->opt.bind && !second->opt.bind) {
0639         /* shift explicit bind()ed addresses to the start */
0640         return -1;
0641     }
0642 
0643     if (!first->opt.bind && second->opt.bind) {
0644         /* shift explicit bind()ed addresses to the start */
0645         return 1;
0646     }
0647 
0648     /* do not sort by default */
0649 
0650     return 0;
0651 }