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) Roman Arutyunyan
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_stream.h>
0011 
0012 
0013 static ngx_int_t ngx_stream_core_preconfiguration(ngx_conf_t *cf);
0014 static void *ngx_stream_core_create_main_conf(ngx_conf_t *cf);
0015 static char *ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf);
0016 static void *ngx_stream_core_create_srv_conf(ngx_conf_t *cf);
0017 static char *ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent,
0018     void *child);
0019 static char *ngx_stream_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
0020     void *conf);
0021 static char *ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
0022     void *conf);
0023 static char *ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
0024     void *conf);
0025 static char *ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
0026     void *conf);
0027 
0028 
0029 static ngx_command_t  ngx_stream_core_commands[] = {
0030 
0031     { ngx_string("variables_hash_max_size"),
0032       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
0033       ngx_conf_set_num_slot,
0034       NGX_STREAM_MAIN_CONF_OFFSET,
0035       offsetof(ngx_stream_core_main_conf_t, variables_hash_max_size),
0036       NULL },
0037 
0038     { ngx_string("variables_hash_bucket_size"),
0039       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
0040       ngx_conf_set_num_slot,
0041       NGX_STREAM_MAIN_CONF_OFFSET,
0042       offsetof(ngx_stream_core_main_conf_t, variables_hash_bucket_size),
0043       NULL },
0044 
0045     { ngx_string("server"),
0046       NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
0047       ngx_stream_core_server,
0048       0,
0049       0,
0050       NULL },
0051 
0052     { ngx_string("listen"),
0053       NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
0054       ngx_stream_core_listen,
0055       NGX_STREAM_SRV_CONF_OFFSET,
0056       0,
0057       NULL },
0058 
0059     { ngx_string("error_log"),
0060       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
0061       ngx_stream_core_error_log,
0062       NGX_STREAM_SRV_CONF_OFFSET,
0063       0,
0064       NULL },
0065 
0066     { ngx_string("resolver"),
0067       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
0068       ngx_stream_core_resolver,
0069       NGX_STREAM_SRV_CONF_OFFSET,
0070       0,
0071       NULL },
0072 
0073     { ngx_string("resolver_timeout"),
0074       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0075       ngx_conf_set_msec_slot,
0076       NGX_STREAM_SRV_CONF_OFFSET,
0077       offsetof(ngx_stream_core_srv_conf_t, resolver_timeout),
0078       NULL },
0079 
0080     { ngx_string("proxy_protocol_timeout"),
0081       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0082       ngx_conf_set_msec_slot,
0083       NGX_STREAM_SRV_CONF_OFFSET,
0084       offsetof(ngx_stream_core_srv_conf_t, proxy_protocol_timeout),
0085       NULL },
0086 
0087     { ngx_string("tcp_nodelay"),
0088       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
0089       ngx_conf_set_flag_slot,
0090       NGX_STREAM_SRV_CONF_OFFSET,
0091       offsetof(ngx_stream_core_srv_conf_t, tcp_nodelay),
0092       NULL },
0093 
0094     { ngx_string("preread_buffer_size"),
0095       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0096       ngx_conf_set_size_slot,
0097       NGX_STREAM_SRV_CONF_OFFSET,
0098       offsetof(ngx_stream_core_srv_conf_t, preread_buffer_size),
0099       NULL },
0100 
0101     { ngx_string("preread_timeout"),
0102       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
0103       ngx_conf_set_msec_slot,
0104       NGX_STREAM_SRV_CONF_OFFSET,
0105       offsetof(ngx_stream_core_srv_conf_t, preread_timeout),
0106       NULL },
0107 
0108       ngx_null_command
0109 };
0110 
0111 
0112 static ngx_stream_module_t  ngx_stream_core_module_ctx = {
0113     ngx_stream_core_preconfiguration,      /* preconfiguration */
0114     NULL,                                  /* postconfiguration */
0115 
0116     ngx_stream_core_create_main_conf,      /* create main configuration */
0117     ngx_stream_core_init_main_conf,        /* init main configuration */
0118 
0119     ngx_stream_core_create_srv_conf,       /* create server configuration */
0120     ngx_stream_core_merge_srv_conf         /* merge server configuration */
0121 };
0122 
0123 
0124 ngx_module_t  ngx_stream_core_module = {
0125     NGX_MODULE_V1,
0126     &ngx_stream_core_module_ctx,           /* module context */
0127     ngx_stream_core_commands,              /* module directives */
0128     NGX_STREAM_MODULE,                     /* module type */
0129     NULL,                                  /* init master */
0130     NULL,                                  /* init module */
0131     NULL,                                  /* init process */
0132     NULL,                                  /* init thread */
0133     NULL,                                  /* exit thread */
0134     NULL,                                  /* exit process */
0135     NULL,                                  /* exit master */
0136     NGX_MODULE_V1_PADDING
0137 };
0138 
0139 
0140 void
0141 ngx_stream_core_run_phases(ngx_stream_session_t *s)
0142 {
0143     ngx_int_t                     rc;
0144     ngx_stream_phase_handler_t   *ph;
0145     ngx_stream_core_main_conf_t  *cmcf;
0146 
0147     cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
0148 
0149     ph = cmcf->phase_engine.handlers;
0150 
0151     while (ph[s->phase_handler].checker) {
0152 
0153         rc = ph[s->phase_handler].checker(s, &ph[s->phase_handler]);
0154 
0155         if (rc == NGX_OK) {
0156             return;
0157         }
0158     }
0159 }
0160 
0161 
0162 ngx_int_t
0163 ngx_stream_core_generic_phase(ngx_stream_session_t *s,
0164     ngx_stream_phase_handler_t *ph)
0165 {
0166     ngx_int_t  rc;
0167 
0168     /*
0169      * generic phase checker,
0170      * used by all phases, except for preread and content
0171      */
0172 
0173     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
0174                    "generic phase: %ui", s->phase_handler);
0175 
0176     rc = ph->handler(s);
0177 
0178     if (rc == NGX_OK) {
0179         s->phase_handler = ph->next;
0180         return NGX_AGAIN;
0181     }
0182 
0183     if (rc == NGX_DECLINED) {
0184         s->phase_handler++;
0185         return NGX_AGAIN;
0186     }
0187 
0188     if (rc == NGX_AGAIN || rc == NGX_DONE) {
0189         return NGX_OK;
0190     }
0191 
0192     if (rc == NGX_ERROR) {
0193         rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
0194     }
0195 
0196     ngx_stream_finalize_session(s, rc);
0197 
0198     return NGX_OK;
0199 }
0200 
0201 
0202 ngx_int_t
0203 ngx_stream_core_preread_phase(ngx_stream_session_t *s,
0204     ngx_stream_phase_handler_t *ph)
0205 {
0206     size_t                       size;
0207     ssize_t                      n;
0208     ngx_int_t                    rc;
0209     ngx_connection_t            *c;
0210     ngx_stream_core_srv_conf_t  *cscf;
0211 
0212     c = s->connection;
0213 
0214     c->log->action = "prereading client data";
0215 
0216     cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
0217 
0218     if (c->read->timedout) {
0219         rc = NGX_STREAM_OK;
0220 
0221     } else if (c->read->timer_set) {
0222         rc = NGX_AGAIN;
0223 
0224     } else {
0225         rc = ph->handler(s);
0226     }
0227 
0228     while (rc == NGX_AGAIN) {
0229 
0230         if (c->buffer == NULL) {
0231             c->buffer = ngx_create_temp_buf(c->pool, cscf->preread_buffer_size);
0232             if (c->buffer == NULL) {
0233                 rc = NGX_ERROR;
0234                 break;
0235             }
0236         }
0237 
0238         size = c->buffer->end - c->buffer->last;
0239 
0240         if (size == 0) {
0241             ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
0242             rc = NGX_STREAM_BAD_REQUEST;
0243             break;
0244         }
0245 
0246         if (c->read->eof) {
0247             rc = NGX_STREAM_OK;
0248             break;
0249         }
0250 
0251         if (!c->read->ready) {
0252             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
0253                 rc = NGX_ERROR;
0254                 break;
0255             }
0256 
0257             if (!c->read->timer_set) {
0258                 ngx_add_timer(c->read, cscf->preread_timeout);
0259             }
0260 
0261             c->read->handler = ngx_stream_session_handler;
0262 
0263             return NGX_OK;
0264         }
0265 
0266         n = c->recv(c, c->buffer->last, size);
0267 
0268         if (n == NGX_ERROR) {
0269             rc = NGX_STREAM_OK;
0270             break;
0271         }
0272 
0273         if (n > 0) {
0274             c->buffer->last += n;
0275         }
0276 
0277         rc = ph->handler(s);
0278     }
0279 
0280     if (c->read->timer_set) {
0281         ngx_del_timer(c->read);
0282     }
0283 
0284     if (rc == NGX_OK) {
0285         s->phase_handler = ph->next;
0286         return NGX_AGAIN;
0287     }
0288 
0289     if (rc == NGX_DECLINED) {
0290         s->phase_handler++;
0291         return NGX_AGAIN;
0292     }
0293 
0294     if (rc == NGX_DONE) {
0295         return NGX_OK;
0296     }
0297 
0298     if (rc == NGX_ERROR) {
0299         rc = NGX_STREAM_INTERNAL_SERVER_ERROR;
0300     }
0301 
0302     ngx_stream_finalize_session(s, rc);
0303 
0304     return NGX_OK;
0305 }
0306 
0307 
0308 ngx_int_t
0309 ngx_stream_core_content_phase(ngx_stream_session_t *s,
0310     ngx_stream_phase_handler_t *ph)
0311 {
0312     int                          tcp_nodelay;
0313     ngx_connection_t            *c;
0314     ngx_stream_core_srv_conf_t  *cscf;
0315 
0316     c = s->connection;
0317 
0318     c->log->action = NULL;
0319 
0320     cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
0321 
0322     if (c->type == SOCK_STREAM
0323         && cscf->tcp_nodelay
0324         && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
0325     {
0326         ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "tcp_nodelay");
0327 
0328         tcp_nodelay = 1;
0329 
0330         if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
0331                        (const void *) &tcp_nodelay, sizeof(int)) == -1)
0332         {
0333             ngx_connection_error(c, ngx_socket_errno,
0334                                  "setsockopt(TCP_NODELAY) failed");
0335             ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
0336             return NGX_OK;
0337         }
0338 
0339         c->tcp_nodelay = NGX_TCP_NODELAY_SET;
0340     }
0341 
0342     cscf->handler(s);
0343 
0344     return NGX_OK;
0345 }
0346 
0347 
0348 static ngx_int_t
0349 ngx_stream_core_preconfiguration(ngx_conf_t *cf)
0350 {
0351     return ngx_stream_variables_add_core_vars(cf);
0352 }
0353 
0354 
0355 static void *
0356 ngx_stream_core_create_main_conf(ngx_conf_t *cf)
0357 {
0358     ngx_stream_core_main_conf_t  *cmcf;
0359 
0360     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_main_conf_t));
0361     if (cmcf == NULL) {
0362         return NULL;
0363     }
0364 
0365     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
0366                        sizeof(ngx_stream_core_srv_conf_t *))
0367         != NGX_OK)
0368     {
0369         return NULL;
0370     }
0371 
0372     if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_stream_listen_t))
0373         != NGX_OK)
0374     {
0375         return NULL;
0376     }
0377 
0378     cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
0379     cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
0380 
0381     return cmcf;
0382 }
0383 
0384 
0385 static char *
0386 ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf)
0387 {
0388     ngx_stream_core_main_conf_t *cmcf = conf;
0389 
0390     ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
0391     ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);
0392 
0393     cmcf->variables_hash_bucket_size =
0394                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
0395 
0396     if (cmcf->ncaptures) {
0397         cmcf->ncaptures = (cmcf->ncaptures + 1) * 3;
0398     }
0399 
0400     return NGX_CONF_OK;
0401 }
0402 
0403 
0404 static void *
0405 ngx_stream_core_create_srv_conf(ngx_conf_t *cf)
0406 {
0407     ngx_stream_core_srv_conf_t  *cscf;
0408 
0409     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_srv_conf_t));
0410     if (cscf == NULL) {
0411         return NULL;
0412     }
0413 
0414     /*
0415      * set by ngx_pcalloc():
0416      *
0417      *     cscf->handler = NULL;
0418      *     cscf->error_log = NULL;
0419      */
0420 
0421     cscf->file_name = cf->conf_file->file.name.data;
0422     cscf->line = cf->conf_file->line;
0423     cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
0424     cscf->proxy_protocol_timeout = NGX_CONF_UNSET_MSEC;
0425     cscf->tcp_nodelay = NGX_CONF_UNSET;
0426     cscf->preread_buffer_size = NGX_CONF_UNSET_SIZE;
0427     cscf->preread_timeout = NGX_CONF_UNSET_MSEC;
0428 
0429     return cscf;
0430 }
0431 
0432 
0433 static char *
0434 ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
0435 {
0436     ngx_stream_core_srv_conf_t *prev = parent;
0437     ngx_stream_core_srv_conf_t *conf = child;
0438 
0439     ngx_conf_merge_msec_value(conf->resolver_timeout,
0440                               prev->resolver_timeout, 30000);
0441 
0442     if (conf->resolver == NULL) {
0443 
0444         if (prev->resolver == NULL) {
0445 
0446             /*
0447              * create dummy resolver in stream {} context
0448              * to inherit it in all servers
0449              */
0450 
0451             prev->resolver = ngx_resolver_create(cf, NULL, 0);
0452             if (prev->resolver == NULL) {
0453                 return NGX_CONF_ERROR;
0454             }
0455         }
0456 
0457         conf->resolver = prev->resolver;
0458     }
0459 
0460     if (conf->handler == NULL) {
0461         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0462                       "no handler for server in %s:%ui",
0463                       conf->file_name, conf->line);
0464         return NGX_CONF_ERROR;
0465     }
0466 
0467     if (conf->error_log == NULL) {
0468         if (prev->error_log) {
0469             conf->error_log = prev->error_log;
0470         } else {
0471             conf->error_log = &cf->cycle->new_log;
0472         }
0473     }
0474 
0475     ngx_conf_merge_msec_value(conf->proxy_protocol_timeout,
0476                               prev->proxy_protocol_timeout, 30000);
0477 
0478     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
0479 
0480     ngx_conf_merge_size_value(conf->preread_buffer_size,
0481                               prev->preread_buffer_size, 16384);
0482 
0483     ngx_conf_merge_msec_value(conf->preread_timeout,
0484                               prev->preread_timeout, 30000);
0485 
0486     return NGX_CONF_OK;
0487 }
0488 
0489 
0490 static char *
0491 ngx_stream_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0492 {
0493     ngx_stream_core_srv_conf_t  *cscf = conf;
0494 
0495     return ngx_log_set_log(cf, &cscf->error_log);
0496 }
0497 
0498 
0499 static char *
0500 ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0501 {
0502     char                         *rv;
0503     void                         *mconf;
0504     ngx_uint_t                    m;
0505     ngx_conf_t                    pcf;
0506     ngx_stream_module_t          *module;
0507     ngx_stream_conf_ctx_t        *ctx, *stream_ctx;
0508     ngx_stream_core_srv_conf_t   *cscf, **cscfp;
0509     ngx_stream_core_main_conf_t  *cmcf;
0510 
0511     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t));
0512     if (ctx == NULL) {
0513         return NGX_CONF_ERROR;
0514     }
0515 
0516     stream_ctx = cf->ctx;
0517     ctx->main_conf = stream_ctx->main_conf;
0518 
0519     /* the server{}'s srv_conf */
0520 
0521     ctx->srv_conf = ngx_pcalloc(cf->pool,
0522                                 sizeof(void *) * ngx_stream_max_module);
0523     if (ctx->srv_conf == NULL) {
0524         return NGX_CONF_ERROR;
0525     }
0526 
0527     for (m = 0; cf->cycle->modules[m]; m++) {
0528         if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) {
0529             continue;
0530         }
0531 
0532         module = cf->cycle->modules[m]->ctx;
0533 
0534         if (module->create_srv_conf) {
0535             mconf = module->create_srv_conf(cf);
0536             if (mconf == NULL) {
0537                 return NGX_CONF_ERROR;
0538             }
0539 
0540             ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf;
0541         }
0542     }
0543 
0544     /* the server configuration context */
0545 
0546     cscf = ctx->srv_conf[ngx_stream_core_module.ctx_index];
0547     cscf->ctx = ctx;
0548 
0549     cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index];
0550 
0551     cscfp = ngx_array_push(&cmcf->servers);
0552     if (cscfp == NULL) {
0553         return NGX_CONF_ERROR;
0554     }
0555 
0556     *cscfp = cscf;
0557 
0558 
0559     /* parse inside server{} */
0560 
0561     pcf = *cf;
0562     cf->ctx = ctx;
0563     cf->cmd_type = NGX_STREAM_SRV_CONF;
0564 
0565     rv = ngx_conf_parse(cf, NULL);
0566 
0567     *cf = pcf;
0568 
0569     if (rv == NGX_CONF_OK && !cscf->listen) {
0570         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0571                       "no \"listen\" is defined for server in %s:%ui",
0572                       cscf->file_name, cscf->line);
0573         return NGX_CONF_ERROR;
0574     }
0575 
0576     return rv;
0577 }
0578 
0579 
0580 static char *
0581 ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0582 {
0583     ngx_stream_core_srv_conf_t  *cscf = conf;
0584 
0585     ngx_str_t                    *value;
0586     ngx_url_t                     u;
0587     ngx_uint_t                    i, backlog;
0588     ngx_stream_listen_t          *ls, *als;
0589     ngx_stream_core_main_conf_t  *cmcf;
0590 
0591     cscf->listen = 1;
0592 
0593     value = cf->args->elts;
0594 
0595     ngx_memzero(&u, sizeof(ngx_url_t));
0596 
0597     u.url = value[1];
0598     u.listen = 1;
0599 
0600     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
0601         if (u.err) {
0602             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0603                                "%s in \"%V\" of the \"listen\" directive",
0604                                u.err, &u.url);
0605         }
0606 
0607         return NGX_CONF_ERROR;
0608     }
0609 
0610     cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
0611 
0612     ls = ngx_array_push(&cmcf->listen);
0613     if (ls == NULL) {
0614         return NGX_CONF_ERROR;
0615     }
0616 
0617     ngx_memzero(ls, sizeof(ngx_stream_listen_t));
0618 
0619     ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen);
0620 
0621     ls->socklen = u.socklen;
0622     ls->backlog = NGX_LISTEN_BACKLOG;
0623     ls->type = SOCK_STREAM;
0624     ls->wildcard = u.wildcard;
0625     ls->ctx = cf->ctx;
0626 
0627 #if (NGX_HAVE_INET6)
0628     ls->ipv6only = 1;
0629 #endif
0630 
0631     backlog = 0;
0632 
0633     for (i = 2; i < cf->args->nelts; i++) {
0634 
0635 #if !(NGX_WIN32)
0636         if (ngx_strcmp(value[i].data, "udp") == 0) {
0637             ls->type = SOCK_DGRAM;
0638             continue;
0639         }
0640 #endif
0641 
0642         if (ngx_strcmp(value[i].data, "bind") == 0) {
0643             ls->bind = 1;
0644             continue;
0645         }
0646 
0647         if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
0648             ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
0649             ls->bind = 1;
0650 
0651             if (ls->backlog == NGX_ERROR || ls->backlog == 0) {
0652                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0653                                    "invalid backlog \"%V\"", &value[i]);
0654                 return NGX_CONF_ERROR;
0655             }
0656 
0657             backlog = 1;
0658 
0659             continue;
0660         }
0661 
0662         if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
0663 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
0664             size_t  len;
0665             u_char  buf[NGX_SOCKADDR_STRLEN];
0666 
0667             if (ls->sockaddr.sockaddr.sa_family == AF_INET6) {
0668 
0669                 if (ngx_strcmp(&value[i].data[10], "n") == 0) {
0670                     ls->ipv6only = 1;
0671 
0672                 } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
0673                     ls->ipv6only = 0;
0674 
0675                 } else {
0676                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0677                                        "invalid ipv6only flags \"%s\"",
0678                                        &value[i].data[9]);
0679                     return NGX_CONF_ERROR;
0680                 }
0681 
0682                 ls->bind = 1;
0683 
0684             } else {
0685                 len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf,
0686                                     NGX_SOCKADDR_STRLEN, 1);
0687 
0688                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0689                                    "ipv6only is not supported "
0690                                    "on addr \"%*s\", ignored", len, buf);
0691             }
0692 
0693             continue;
0694 #else
0695             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0696                                "bind ipv6only is not supported "
0697                                "on this platform");
0698             return NGX_CONF_ERROR;
0699 #endif
0700         }
0701 
0702         if (ngx_strcmp(value[i].data, "reuseport") == 0) {
0703 #if (NGX_HAVE_REUSEPORT)
0704             ls->reuseport = 1;
0705             ls->bind = 1;
0706 #else
0707             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0708                                "reuseport is not supported "
0709                                "on this platform, ignored");
0710 #endif
0711             continue;
0712         }
0713 
0714         if (ngx_strcmp(value[i].data, "ssl") == 0) {
0715 #if (NGX_STREAM_SSL)
0716             ls->ssl = 1;
0717             continue;
0718 #else
0719             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0720                                "the \"ssl\" parameter requires "
0721                                "ngx_stream_ssl_module");
0722             return NGX_CONF_ERROR;
0723 #endif
0724         }
0725 
0726         if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {
0727 
0728             if (ngx_strcmp(&value[i].data[13], "on") == 0) {
0729                 ls->so_keepalive = 1;
0730 
0731             } else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
0732                 ls->so_keepalive = 2;
0733 
0734             } else {
0735 
0736 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0737                 u_char     *p, *end;
0738                 ngx_str_t   s;
0739 
0740                 end = value[i].data + value[i].len;
0741                 s.data = value[i].data + 13;
0742 
0743                 p = ngx_strlchr(s.data, end, ':');
0744                 if (p == NULL) {
0745                     p = end;
0746                 }
0747 
0748                 if (p > s.data) {
0749                     s.len = p - s.data;
0750 
0751                     ls->tcp_keepidle = ngx_parse_time(&s, 1);
0752                     if (ls->tcp_keepidle == (time_t) NGX_ERROR) {
0753                         goto invalid_so_keepalive;
0754                     }
0755                 }
0756 
0757                 s.data = (p < end) ? (p + 1) : end;
0758 
0759                 p = ngx_strlchr(s.data, end, ':');
0760                 if (p == NULL) {
0761                     p = end;
0762                 }
0763 
0764                 if (p > s.data) {
0765                     s.len = p - s.data;
0766 
0767                     ls->tcp_keepintvl = ngx_parse_time(&s, 1);
0768                     if (ls->tcp_keepintvl == (time_t) NGX_ERROR) {
0769                         goto invalid_so_keepalive;
0770                     }
0771                 }
0772 
0773                 s.data = (p < end) ? (p + 1) : end;
0774 
0775                 if (s.data < end) {
0776                     s.len = end - s.data;
0777 
0778                     ls->tcp_keepcnt = ngx_atoi(s.data, s.len);
0779                     if (ls->tcp_keepcnt == NGX_ERROR) {
0780                         goto invalid_so_keepalive;
0781                     }
0782                 }
0783 
0784                 if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0
0785                     && ls->tcp_keepcnt == 0)
0786                 {
0787                     goto invalid_so_keepalive;
0788                 }
0789 
0790                 ls->so_keepalive = 1;
0791 
0792 #else
0793 
0794                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0795                                    "the \"so_keepalive\" parameter accepts "
0796                                    "only \"on\" or \"off\" on this platform");
0797                 return NGX_CONF_ERROR;
0798 
0799 #endif
0800             }
0801 
0802             ls->bind = 1;
0803 
0804             continue;
0805 
0806 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0807         invalid_so_keepalive:
0808 
0809             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0810                                "invalid so_keepalive value: \"%s\"",
0811                                &value[i].data[13]);
0812             return NGX_CONF_ERROR;
0813 #endif
0814         }
0815 
0816         if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) {
0817             ls->proxy_protocol = 1;
0818             continue;
0819         }
0820 
0821         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0822                            "the invalid \"%V\" parameter", &value[i]);
0823         return NGX_CONF_ERROR;
0824     }
0825 
0826     if (ls->type == SOCK_DGRAM) {
0827         if (backlog) {
0828             return "\"backlog\" parameter is incompatible with \"udp\"";
0829         }
0830 
0831 #if (NGX_STREAM_SSL)
0832         if (ls->ssl) {
0833             return "\"ssl\" parameter is incompatible with \"udp\"";
0834         }
0835 #endif
0836 
0837         if (ls->so_keepalive) {
0838             return "\"so_keepalive\" parameter is incompatible with \"udp\"";
0839         }
0840 
0841         if (ls->proxy_protocol) {
0842             return "\"proxy_protocol\" parameter is incompatible with \"udp\"";
0843         }
0844     }
0845 
0846     als = cmcf->listen.elts;
0847 
0848     for (i = 0; i < cmcf->listen.nelts - 1; i++) {
0849         if (ls->type != als[i].type) {
0850             continue;
0851         }
0852 
0853         if (ngx_cmp_sockaddr(&als[i].sockaddr.sockaddr, als[i].socklen,
0854                              &ls->sockaddr.sockaddr, ls->socklen, 1)
0855             != NGX_OK)
0856         {
0857             continue;
0858         }
0859 
0860         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0861                            "duplicate \"%V\" address and port pair", &u.url);
0862         return NGX_CONF_ERROR;
0863     }
0864 
0865     return NGX_CONF_OK;
0866 }
0867 
0868 
0869 static char *
0870 ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0871 {
0872     ngx_stream_core_srv_conf_t  *cscf = conf;
0873 
0874     ngx_str_t  *value;
0875 
0876     if (cscf->resolver) {
0877         return "is duplicate";
0878     }
0879 
0880     value = cf->args->elts;
0881 
0882     cscf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
0883     if (cscf->resolver == NULL) {
0884         return NGX_CONF_ERROR;
0885     }
0886 
0887     return NGX_CONF_OK;
0888 }