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     ngx_connection_t            *c;
0313     ngx_stream_core_srv_conf_t  *cscf;
0314 
0315     c = s->connection;
0316 
0317     c->log->action = NULL;
0318 
0319     cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
0320 
0321     if (c->type == SOCK_STREAM
0322         && cscf->tcp_nodelay
0323         && ngx_tcp_nodelay(c) != NGX_OK)
0324     {
0325         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
0326         return NGX_OK;
0327     }
0328 
0329     cscf->handler(s);
0330 
0331     return NGX_OK;
0332 }
0333 
0334 
0335 static ngx_int_t
0336 ngx_stream_core_preconfiguration(ngx_conf_t *cf)
0337 {
0338     return ngx_stream_variables_add_core_vars(cf);
0339 }
0340 
0341 
0342 static void *
0343 ngx_stream_core_create_main_conf(ngx_conf_t *cf)
0344 {
0345     ngx_stream_core_main_conf_t  *cmcf;
0346 
0347     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_main_conf_t));
0348     if (cmcf == NULL) {
0349         return NULL;
0350     }
0351 
0352     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
0353                        sizeof(ngx_stream_core_srv_conf_t *))
0354         != NGX_OK)
0355     {
0356         return NULL;
0357     }
0358 
0359     if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_stream_listen_t))
0360         != NGX_OK)
0361     {
0362         return NULL;
0363     }
0364 
0365     cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
0366     cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
0367 
0368     return cmcf;
0369 }
0370 
0371 
0372 static char *
0373 ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf)
0374 {
0375     ngx_stream_core_main_conf_t *cmcf = conf;
0376 
0377     ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
0378     ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);
0379 
0380     cmcf->variables_hash_bucket_size =
0381                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
0382 
0383     if (cmcf->ncaptures) {
0384         cmcf->ncaptures = (cmcf->ncaptures + 1) * 3;
0385     }
0386 
0387     return NGX_CONF_OK;
0388 }
0389 
0390 
0391 static void *
0392 ngx_stream_core_create_srv_conf(ngx_conf_t *cf)
0393 {
0394     ngx_stream_core_srv_conf_t  *cscf;
0395 
0396     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_core_srv_conf_t));
0397     if (cscf == NULL) {
0398         return NULL;
0399     }
0400 
0401     /*
0402      * set by ngx_pcalloc():
0403      *
0404      *     cscf->handler = NULL;
0405      *     cscf->error_log = NULL;
0406      */
0407 
0408     cscf->file_name = cf->conf_file->file.name.data;
0409     cscf->line = cf->conf_file->line;
0410     cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
0411     cscf->proxy_protocol_timeout = NGX_CONF_UNSET_MSEC;
0412     cscf->tcp_nodelay = NGX_CONF_UNSET;
0413     cscf->preread_buffer_size = NGX_CONF_UNSET_SIZE;
0414     cscf->preread_timeout = NGX_CONF_UNSET_MSEC;
0415 
0416     return cscf;
0417 }
0418 
0419 
0420 static char *
0421 ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
0422 {
0423     ngx_stream_core_srv_conf_t *prev = parent;
0424     ngx_stream_core_srv_conf_t *conf = child;
0425 
0426     ngx_conf_merge_msec_value(conf->resolver_timeout,
0427                               prev->resolver_timeout, 30000);
0428 
0429     if (conf->resolver == NULL) {
0430 
0431         if (prev->resolver == NULL) {
0432 
0433             /*
0434              * create dummy resolver in stream {} context
0435              * to inherit it in all servers
0436              */
0437 
0438             prev->resolver = ngx_resolver_create(cf, NULL, 0);
0439             if (prev->resolver == NULL) {
0440                 return NGX_CONF_ERROR;
0441             }
0442         }
0443 
0444         conf->resolver = prev->resolver;
0445     }
0446 
0447     if (conf->handler == NULL) {
0448         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0449                       "no handler for server in %s:%ui",
0450                       conf->file_name, conf->line);
0451         return NGX_CONF_ERROR;
0452     }
0453 
0454     if (conf->error_log == NULL) {
0455         if (prev->error_log) {
0456             conf->error_log = prev->error_log;
0457         } else {
0458             conf->error_log = &cf->cycle->new_log;
0459         }
0460     }
0461 
0462     ngx_conf_merge_msec_value(conf->proxy_protocol_timeout,
0463                               prev->proxy_protocol_timeout, 30000);
0464 
0465     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
0466 
0467     ngx_conf_merge_size_value(conf->preread_buffer_size,
0468                               prev->preread_buffer_size, 16384);
0469 
0470     ngx_conf_merge_msec_value(conf->preread_timeout,
0471                               prev->preread_timeout, 30000);
0472 
0473     return NGX_CONF_OK;
0474 }
0475 
0476 
0477 static char *
0478 ngx_stream_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0479 {
0480     ngx_stream_core_srv_conf_t  *cscf = conf;
0481 
0482     return ngx_log_set_log(cf, &cscf->error_log);
0483 }
0484 
0485 
0486 static char *
0487 ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0488 {
0489     char                         *rv;
0490     void                         *mconf;
0491     ngx_uint_t                    m;
0492     ngx_conf_t                    pcf;
0493     ngx_stream_module_t          *module;
0494     ngx_stream_conf_ctx_t        *ctx, *stream_ctx;
0495     ngx_stream_core_srv_conf_t   *cscf, **cscfp;
0496     ngx_stream_core_main_conf_t  *cmcf;
0497 
0498     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t));
0499     if (ctx == NULL) {
0500         return NGX_CONF_ERROR;
0501     }
0502 
0503     stream_ctx = cf->ctx;
0504     ctx->main_conf = stream_ctx->main_conf;
0505 
0506     /* the server{}'s srv_conf */
0507 
0508     ctx->srv_conf = ngx_pcalloc(cf->pool,
0509                                 sizeof(void *) * ngx_stream_max_module);
0510     if (ctx->srv_conf == NULL) {
0511         return NGX_CONF_ERROR;
0512     }
0513 
0514     for (m = 0; cf->cycle->modules[m]; m++) {
0515         if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) {
0516             continue;
0517         }
0518 
0519         module = cf->cycle->modules[m]->ctx;
0520 
0521         if (module->create_srv_conf) {
0522             mconf = module->create_srv_conf(cf);
0523             if (mconf == NULL) {
0524                 return NGX_CONF_ERROR;
0525             }
0526 
0527             ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf;
0528         }
0529     }
0530 
0531     /* the server configuration context */
0532 
0533     cscf = ctx->srv_conf[ngx_stream_core_module.ctx_index];
0534     cscf->ctx = ctx;
0535 
0536     cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index];
0537 
0538     cscfp = ngx_array_push(&cmcf->servers);
0539     if (cscfp == NULL) {
0540         return NGX_CONF_ERROR;
0541     }
0542 
0543     *cscfp = cscf;
0544 
0545 
0546     /* parse inside server{} */
0547 
0548     pcf = *cf;
0549     cf->ctx = ctx;
0550     cf->cmd_type = NGX_STREAM_SRV_CONF;
0551 
0552     rv = ngx_conf_parse(cf, NULL);
0553 
0554     *cf = pcf;
0555 
0556     if (rv == NGX_CONF_OK && !cscf->listen) {
0557         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0558                       "no \"listen\" is defined for server in %s:%ui",
0559                       cscf->file_name, cscf->line);
0560         return NGX_CONF_ERROR;
0561     }
0562 
0563     return rv;
0564 }
0565 
0566 
0567 static char *
0568 ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0569 {
0570     ngx_stream_core_srv_conf_t  *cscf = conf;
0571 
0572     ngx_str_t                    *value, size;
0573     ngx_url_t                     u;
0574     ngx_uint_t                    i, backlog;
0575     ngx_stream_listen_t          *ls, *als;
0576     ngx_stream_core_main_conf_t  *cmcf;
0577 
0578     cscf->listen = 1;
0579 
0580     value = cf->args->elts;
0581 
0582     ngx_memzero(&u, sizeof(ngx_url_t));
0583 
0584     u.url = value[1];
0585     u.listen = 1;
0586 
0587     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
0588         if (u.err) {
0589             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0590                                "%s in \"%V\" of the \"listen\" directive",
0591                                u.err, &u.url);
0592         }
0593 
0594         return NGX_CONF_ERROR;
0595     }
0596 
0597     cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
0598 
0599     ls = ngx_array_push(&cmcf->listen);
0600     if (ls == NULL) {
0601         return NGX_CONF_ERROR;
0602     }
0603 
0604     ngx_memzero(ls, sizeof(ngx_stream_listen_t));
0605 
0606     ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen);
0607 
0608     ls->socklen = u.socklen;
0609     ls->backlog = NGX_LISTEN_BACKLOG;
0610     ls->rcvbuf = -1;
0611     ls->sndbuf = -1;
0612     ls->type = SOCK_STREAM;
0613     ls->wildcard = u.wildcard;
0614     ls->ctx = cf->ctx;
0615 
0616 #if (NGX_HAVE_INET6)
0617     ls->ipv6only = 1;
0618 #endif
0619 
0620     backlog = 0;
0621 
0622     for (i = 2; i < cf->args->nelts; i++) {
0623 
0624 #if !(NGX_WIN32)
0625         if (ngx_strcmp(value[i].data, "udp") == 0) {
0626             ls->type = SOCK_DGRAM;
0627             continue;
0628         }
0629 #endif
0630 
0631         if (ngx_strcmp(value[i].data, "bind") == 0) {
0632             ls->bind = 1;
0633             continue;
0634         }
0635 
0636         if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
0637             ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
0638             ls->bind = 1;
0639 
0640             if (ls->backlog == NGX_ERROR || ls->backlog == 0) {
0641                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0642                                    "invalid backlog \"%V\"", &value[i]);
0643                 return NGX_CONF_ERROR;
0644             }
0645 
0646             backlog = 1;
0647 
0648             continue;
0649         }
0650 
0651         if (ngx_strncmp(value[i].data, "rcvbuf=", 7) == 0) {
0652             size.len = value[i].len - 7;
0653             size.data = value[i].data + 7;
0654 
0655             ls->rcvbuf = ngx_parse_size(&size);
0656             ls->bind = 1;
0657 
0658             if (ls->rcvbuf == NGX_ERROR) {
0659                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0660                                    "invalid rcvbuf \"%V\"", &value[i]);
0661                 return NGX_CONF_ERROR;
0662             }
0663 
0664             continue;
0665         }
0666 
0667         if (ngx_strncmp(value[i].data, "sndbuf=", 7) == 0) {
0668             size.len = value[i].len - 7;
0669             size.data = value[i].data + 7;
0670 
0671             ls->sndbuf = ngx_parse_size(&size);
0672             ls->bind = 1;
0673 
0674             if (ls->sndbuf == NGX_ERROR) {
0675                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0676                                    "invalid sndbuf \"%V\"", &value[i]);
0677                 return NGX_CONF_ERROR;
0678             }
0679 
0680             continue;
0681         }
0682 
0683         if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
0684 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
0685             size_t  len;
0686             u_char  buf[NGX_SOCKADDR_STRLEN];
0687 
0688             if (ls->sockaddr.sockaddr.sa_family == AF_INET6) {
0689 
0690                 if (ngx_strcmp(&value[i].data[10], "n") == 0) {
0691                     ls->ipv6only = 1;
0692 
0693                 } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
0694                     ls->ipv6only = 0;
0695 
0696                 } else {
0697                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0698                                        "invalid ipv6only flags \"%s\"",
0699                                        &value[i].data[9]);
0700                     return NGX_CONF_ERROR;
0701                 }
0702 
0703                 ls->bind = 1;
0704 
0705             } else {
0706                 len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf,
0707                                     NGX_SOCKADDR_STRLEN, 1);
0708 
0709                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0710                                    "ipv6only is not supported "
0711                                    "on addr \"%*s\", ignored", len, buf);
0712             }
0713 
0714             continue;
0715 #else
0716             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0717                                "bind ipv6only is not supported "
0718                                "on this platform");
0719             return NGX_CONF_ERROR;
0720 #endif
0721         }
0722 
0723         if (ngx_strcmp(value[i].data, "reuseport") == 0) {
0724 #if (NGX_HAVE_REUSEPORT)
0725             ls->reuseport = 1;
0726             ls->bind = 1;
0727 #else
0728             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0729                                "reuseport is not supported "
0730                                "on this platform, ignored");
0731 #endif
0732             continue;
0733         }
0734 
0735         if (ngx_strcmp(value[i].data, "ssl") == 0) {
0736 #if (NGX_STREAM_SSL)
0737             ls->ssl = 1;
0738             continue;
0739 #else
0740             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0741                                "the \"ssl\" parameter requires "
0742                                "ngx_stream_ssl_module");
0743             return NGX_CONF_ERROR;
0744 #endif
0745         }
0746 
0747         if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {
0748 
0749             if (ngx_strcmp(&value[i].data[13], "on") == 0) {
0750                 ls->so_keepalive = 1;
0751 
0752             } else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
0753                 ls->so_keepalive = 2;
0754 
0755             } else {
0756 
0757 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0758                 u_char     *p, *end;
0759                 ngx_str_t   s;
0760 
0761                 end = value[i].data + value[i].len;
0762                 s.data = value[i].data + 13;
0763 
0764                 p = ngx_strlchr(s.data, end, ':');
0765                 if (p == NULL) {
0766                     p = end;
0767                 }
0768 
0769                 if (p > s.data) {
0770                     s.len = p - s.data;
0771 
0772                     ls->tcp_keepidle = ngx_parse_time(&s, 1);
0773                     if (ls->tcp_keepidle == (time_t) NGX_ERROR) {
0774                         goto invalid_so_keepalive;
0775                     }
0776                 }
0777 
0778                 s.data = (p < end) ? (p + 1) : end;
0779 
0780                 p = ngx_strlchr(s.data, end, ':');
0781                 if (p == NULL) {
0782                     p = end;
0783                 }
0784 
0785                 if (p > s.data) {
0786                     s.len = p - s.data;
0787 
0788                     ls->tcp_keepintvl = ngx_parse_time(&s, 1);
0789                     if (ls->tcp_keepintvl == (time_t) NGX_ERROR) {
0790                         goto invalid_so_keepalive;
0791                     }
0792                 }
0793 
0794                 s.data = (p < end) ? (p + 1) : end;
0795 
0796                 if (s.data < end) {
0797                     s.len = end - s.data;
0798 
0799                     ls->tcp_keepcnt = ngx_atoi(s.data, s.len);
0800                     if (ls->tcp_keepcnt == NGX_ERROR) {
0801                         goto invalid_so_keepalive;
0802                     }
0803                 }
0804 
0805                 if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0
0806                     && ls->tcp_keepcnt == 0)
0807                 {
0808                     goto invalid_so_keepalive;
0809                 }
0810 
0811                 ls->so_keepalive = 1;
0812 
0813 #else
0814 
0815                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0816                                    "the \"so_keepalive\" parameter accepts "
0817                                    "only \"on\" or \"off\" on this platform");
0818                 return NGX_CONF_ERROR;
0819 
0820 #endif
0821             }
0822 
0823             ls->bind = 1;
0824 
0825             continue;
0826 
0827 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
0828         invalid_so_keepalive:
0829 
0830             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0831                                "invalid so_keepalive value: \"%s\"",
0832                                &value[i].data[13]);
0833             return NGX_CONF_ERROR;
0834 #endif
0835         }
0836 
0837         if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) {
0838             ls->proxy_protocol = 1;
0839             continue;
0840         }
0841 
0842         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0843                            "the invalid \"%V\" parameter", &value[i]);
0844         return NGX_CONF_ERROR;
0845     }
0846 
0847     if (ls->type == SOCK_DGRAM) {
0848         if (backlog) {
0849             return "\"backlog\" parameter is incompatible with \"udp\"";
0850         }
0851 
0852 #if (NGX_STREAM_SSL)
0853         if (ls->ssl) {
0854             return "\"ssl\" parameter is incompatible with \"udp\"";
0855         }
0856 #endif
0857 
0858         if (ls->so_keepalive) {
0859             return "\"so_keepalive\" parameter is incompatible with \"udp\"";
0860         }
0861 
0862         if (ls->proxy_protocol) {
0863             return "\"proxy_protocol\" parameter is incompatible with \"udp\"";
0864         }
0865     }
0866 
0867     als = cmcf->listen.elts;
0868 
0869     for (i = 0; i < cmcf->listen.nelts - 1; i++) {
0870         if (ls->type != als[i].type) {
0871             continue;
0872         }
0873 
0874         if (ngx_cmp_sockaddr(&als[i].sockaddr.sockaddr, als[i].socklen,
0875                              &ls->sockaddr.sockaddr, ls->socklen, 1)
0876             != NGX_OK)
0877         {
0878             continue;
0879         }
0880 
0881         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0882                            "duplicate \"%V\" address and port pair", &u.url);
0883         return NGX_CONF_ERROR;
0884     }
0885 
0886     return NGX_CONF_OK;
0887 }
0888 
0889 
0890 static char *
0891 ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0892 {
0893     ngx_stream_core_srv_conf_t  *cscf = conf;
0894 
0895     ngx_str_t  *value;
0896 
0897     if (cscf->resolver) {
0898         return "is duplicate";
0899     }
0900 
0901     value = cf->args->elts;
0902 
0903     cscf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
0904     if (cscf->resolver == NULL) {
0905         return NGX_CONF_ERROR;
0906     }
0907 
0908     return NGX_CONF_OK;
0909 }