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
12
13ngx_os_io_t  ngx_io;
14
15
16static void ngx_drain_connections(ngx_cycle_t *cycle);
17
18
19ngx_listening_t *
20ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr,
21    socklen_t socklen)
22{
23    size_t            len;
24    ngx_listening_t  *ls;
25    struct sockaddr  *sa;
26    u_char            text[NGX_SOCKADDR_STRLEN];
27
28    ls = ngx_array_push(&cf->cycle->listening);
29    if (ls == NULL) {
30        return NULL;
31    }
32
33    ngx_memzero(ls, sizeof(ngx_listening_t));
34
35    sa = ngx_palloc(cf->pool, socklen);
36    if (sa == NULL) {
37        return NULL;
38    }
39
40    ngx_memcpy(sa, sockaddr, socklen);
41
42    ls->sockaddr = sa;
43    ls->socklen = socklen;
44
45    len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1);
46    ls->addr_text.len = len;
47
48    switch (ls->sockaddr->sa_family) {
49#if (NGX_HAVE_INET6)
50    case AF_INET6:
51        ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
52        break;
53#endif
54#if (NGX_HAVE_UNIX_DOMAIN)
55    case AF_UNIX:
56        ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
57        len++;
58        break;
59#endif
60    case AF_INET:
61        ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
62        break;
63    default:
64        ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
65        break;
66    }
67
68    ls->addr_text.data = ngx_pnalloc(cf->pool, len);
69    if (ls->addr_text.data == NULL) {
70        return NULL;
71    }
72
73    ngx_memcpy(ls->addr_text.data, text, len);
74
75    ls->fd = (ngx_socket_t) -1;
76    ls->type = SOCK_STREAM;
77
78    ls->backlog = NGX_LISTEN_BACKLOG;
79    ls->rcvbuf = -1;
80    ls->sndbuf = -1;
81
82#if (NGX_HAVE_SETFIB)
83    ls->setfib = -1;
84#endif
85
86#if (NGX_HAVE_TCP_FASTOPEN)
87    ls->fastopen = -1;
88#endif
89
90    return ls;
91}
92
93
94ngx_int_t
95ngx_clone_listening(ngx_conf_t *cf, ngx_listening_t *ls)
96{
97#if (NGX_HAVE_REUSEPORT)
98
99    ngx_int_t         n;
100    ngx_core_conf_t  *ccf;
101    ngx_listening_t   ols;
102
103    if (!ls->reuseport) {
104        return NGX_OK;
105    }
106
107    ols = *ls;
108
109    ccf = (ngx_core_conf_t *) ngx_get_conf(cf->cycle->conf_ctx,
110                                           ngx_core_module);
111
112    for (n = 1; n < ccf->worker_processes; n++) {
113
114        /* create a socket for each worker process */
115
116        ls = ngx_array_push(&cf->cycle->listening);
117        if (ls == NULL) {
118            return NGX_ERROR;
119        }
120
121        *ls = ols;
122        ls->worker = n;
123    }
124
125#endif
126
127    return NGX_OK;
128}
129
130
131ngx_int_t
132ngx_set_inherited_sockets(ngx_cycle_t *cycle)
133{
134    size_t                     len;
135    ngx_uint_t                 i;
136    ngx_listening_t           *ls;
137    socklen_t                  olen;
138#if (NGX_HAVE_DEFERRED_ACCEPT || NGX_HAVE_TCP_FASTOPEN)
139    ngx_err_t                  err;
140#endif
141#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
142    struct accept_filter_arg   af;
143#endif
144#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
145    int                        timeout;
146#endif
147#if (NGX_HAVE_REUSEPORT)
148    int                        reuseport;
149#endif
150
151    ls = cycle->listening.elts;
152    for (i = 0; i < cycle->listening.nelts; i++) {
153
154        ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(ngx_sockaddr_t));
155        if (ls[i].sockaddr == NULL) {
156            return NGX_ERROR;
157        }
158
159        ls[i].socklen = sizeof(ngx_sockaddr_t);
160        if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) {
161            ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
162                          "getsockname() of the inherited "
163                          "socket #%d failed", ls[i].fd);
164            ls[i].ignore = 1;
165            continue;
166        }
167
168        switch (ls[i].sockaddr->sa_family) {
169
170#if (NGX_HAVE_INET6)
171        case AF_INET6:
172            ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
173            len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
174            break;
175#endif
176
177#if (NGX_HAVE_UNIX_DOMAIN)
178        case AF_UNIX:
179            ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
180            len = NGX_UNIX_ADDRSTRLEN;
181            break;
182#endif
183
184        case AF_INET:
185            ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
186            len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
187            break;
188
189        default:
190            ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
191                          "the inherited socket #%d has "
192                          "an unsupported protocol family", ls[i].fd);
193            ls[i].ignore = 1;
194            continue;
195        }
196
197        ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len);
198        if (ls[i].addr_text.data == NULL) {
199            return NGX_ERROR;
200        }
201
202        len = ngx_sock_ntop(ls[i].sockaddr, ls[i].socklen,
203                            ls[i].addr_text.data, len, 1);
204        if (len == 0) {
205            return NGX_ERROR;
206        }
207
208        ls[i].addr_text.len = len;
209
210        ls[i].backlog = NGX_LISTEN_BACKLOG;
211
212        olen = sizeof(int);
213
214        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_TYPE, (void *) &ls[i].type,
215                       &olen)
216            == -1)
217        {
218            ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
219                          "getsockopt(SO_TYPE) %V failed", &ls[i].addr_text);
220            ls[i].ignore = 1;
221            continue;
222        }
223
224        olen = sizeof(int);
225
226        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf,
227                       &olen)
228            == -1)
229        {
230            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
231                          "getsockopt(SO_RCVBUF) %V failed, ignored",
232                          &ls[i].addr_text);
233
234            ls[i].rcvbuf = -1;
235        }
236
237        olen = sizeof(int);
238
239        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (void *) &ls[i].sndbuf,
240                       &olen)
241            == -1)
242        {
243            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
244                          "getsockopt(SO_SNDBUF) %V failed, ignored",
245                          &ls[i].addr_text);
246
247            ls[i].sndbuf = -1;
248        }
249
250#if 0
251        /* SO_SETFIB is currently a set only option */
252
253#if (NGX_HAVE_SETFIB)
254
255        olen = sizeof(int);
256
257        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
258                       (void *) &ls[i].setfib, &olen)
259            == -1)
260        {
261            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
262                          "getsockopt(SO_SETFIB) %V failed, ignored",
263                          &ls[i].addr_text);
264
265            ls[i].setfib = -1;
266        }
267
268#endif
269#endif
270
271#if (NGX_HAVE_REUSEPORT)
272
273        reuseport = 0;
274        olen = sizeof(int);
275
276        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT,
277                       (void *) &reuseport, &olen)
278            == -1)
279        {
280            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
281                          "getsockopt(SO_REUSEPORT) %V failed, ignored",
282                          &ls[i].addr_text);
283
284        } else {
285            ls[i].reuseport = reuseport ? 1 : 0;
286        }
287
288#endif
289
290        if (ls[i].type != SOCK_STREAM) {
291            continue;
292        }
293
294#if (NGX_HAVE_TCP_FASTOPEN)
295
296        olen = sizeof(int);
297
298        if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
299                       (void *) &ls[i].fastopen, &olen)
300            == -1)
301        {
302            err = ngx_socket_errno;
303
304            if (err != NGX_EOPNOTSUPP && err != NGX_ENOPROTOOPT) {
305                ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
306                              "getsockopt(TCP_FASTOPEN) %V failed, ignored",
307                              &ls[i].addr_text);
308            }
309
310            ls[i].fastopen = -1;
311        }
312
313#endif
314
315#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
316
317        ngx_memzero(&af, sizeof(struct accept_filter_arg));
318        olen = sizeof(struct accept_filter_arg);
319
320        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
321            == -1)
322        {
323            err = ngx_socket_errno;
324
325            if (err == NGX_EINVAL) {
326                continue;
327            }
328
329            ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
330                          "getsockopt(SO_ACCEPTFILTER) for %V failed, ignored",
331                          &ls[i].addr_text);
332            continue;
333        }
334
335        if (olen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
336            continue;
337        }
338
339        ls[i].accept_filter = ngx_palloc(cycle->pool, 16);
340        if (ls[i].accept_filter == NULL) {
341            return NGX_ERROR;
342        }
343
344        (void) ngx_cpystrn((u_char *) ls[i].accept_filter,
345                           (u_char *) af.af_name, 16);
346#endif
347
348#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
349
350        timeout = 0;
351        olen = sizeof(int);
352
353        if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
354            == -1)
355        {
356            err = ngx_socket_errno;
357
358            if (err == NGX_EOPNOTSUPP) {
359                continue;
360            }
361
362            ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
363                          "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
364                          &ls[i].addr_text);
365            continue;
366        }
367
368        if (olen < sizeof(int) || timeout == 0) {
369            continue;
370        }
371
372        ls[i].deferred_accept = 1;
373#endif
374    }
375
376    return NGX_OK;
377}
378
379
380ngx_int_t
381ngx_open_listening_sockets(ngx_cycle_t *cycle)
382{
383    int               reuseaddr;
384    ngx_uint_t        i, tries, failed;
385    ngx_err_t         err;
386    ngx_log_t        *log;
387    ngx_socket_t      s;
388    ngx_listening_t  *ls;
389
390    reuseaddr = 1;
391#if (NGX_SUPPRESS_WARN)
392    failed = 0;
393#endif
394
395    log = cycle->log;
396
397    /* TODO: configurable try number */
398
399    for (tries = 5; tries; tries--) {
400        failed = 0;
401
402        /* for each listening socket */
403
404        ls = cycle->listening.elts;
405        for (i = 0; i < cycle->listening.nelts; i++) {
406
407            if (ls[i].ignore) {
408                continue;
409            }
410
411#if (NGX_HAVE_REUSEPORT)
412
413            if (ls[i].add_reuseport) {
414
415                /*
416                 * to allow transition from a socket without SO_REUSEPORT
417                 * to multiple sockets with SO_REUSEPORT, we have to set
418                 * SO_REUSEPORT on the old socket before opening new ones
419                 */
420
421                int  reuseport = 1;
422
423                if (setsockopt(ls[i].fd, SOL_SOCKET, SO_REUSEPORT,
424                               (const void *) &reuseport, sizeof(int))
425                    == -1)
426                {
427                    ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
428                                  "setsockopt(SO_REUSEPORT) %V failed, ignored",
429                                  &ls[i].addr_text);
430                }
431
432                ls[i].add_reuseport = 0;
433            }
434#endif
435
436            if (ls[i].fd != (ngx_socket_t) -1) {
437                continue;
438            }
439
440            if (ls[i].inherited) {
441
442                /* TODO: close on exit */
443                /* TODO: nonblocking */
444                /* TODO: deferred accept */
445
446                continue;
447            }
448
449            s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
450
451            if (s == (ngx_socket_t) -1) {
452                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
453                              ngx_socket_n " %V failed", &ls[i].addr_text);
454                return NGX_ERROR;
455            }
456
457            if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
458                           (const void *) &reuseaddr, sizeof(int))
459                == -1)
460            {
461                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
462                              "setsockopt(SO_REUSEADDR) %V failed",
463                              &ls[i].addr_text);
464
465                if (ngx_close_socket(s) == -1) {
466                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
467                                  ngx_close_socket_n " %V failed",
468                                  &ls[i].addr_text);
469                }
470
471                return NGX_ERROR;
472            }
473
474#if (NGX_HAVE_REUSEPORT)
475
476            if (ls[i].reuseport) {
477                int  reuseport;
478
479                reuseport = 1;
480
481                if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT,
482                               (const void *) &reuseport, sizeof(int))
483                    == -1)
484                {
485                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
486                                  "setsockopt(SO_REUSEPORT) %V failed, ignored",
487                                  &ls[i].addr_text);
488
489                    if (ngx_close_socket(s) == -1) {
490                        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
491                                      ngx_close_socket_n " %V failed",
492                                      &ls[i].addr_text);
493                    }
494
495                    return NGX_ERROR;
496                }
497            }
498#endif
499
500#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
501
502            if (ls[i].sockaddr->sa_family == AF_INET6) {
503                int  ipv6only;
504
505                ipv6only = ls[i].ipv6only;
506
507                if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
508                               (const void *) &ipv6only, sizeof(int))
509                    == -1)
510                {
511                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
512                                  "setsockopt(IPV6_V6ONLY) %V failed, ignored",
513                                  &ls[i].addr_text);
514                }
515            }
516#endif
517            /* TODO: close on exit */
518
519            if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
520                if (ngx_nonblocking(s) == -1) {
521                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
522                                  ngx_nonblocking_n " %V failed",
523                                  &ls[i].addr_text);
524
525                    if (ngx_close_socket(s) == -1) {
526                        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
527                                      ngx_close_socket_n " %V failed",
528                                      &ls[i].addr_text);
529                    }
530
531                    return NGX_ERROR;
532                }
533            }
534
535            ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0,
536                           "bind() %V #%d ", &ls[i].addr_text, s);
537
538            if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
539                err = ngx_socket_errno;
540
541                if (err != NGX_EADDRINUSE || !ngx_test_config) {
542                    ngx_log_error(NGX_LOG_EMERG, log, err,
543                                  "bind() to %V failed", &ls[i].addr_text);
544                }
545
546                if (ngx_close_socket(s) == -1) {
547                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
548                                  ngx_close_socket_n " %V failed",
549                                  &ls[i].addr_text);
550                }
551
552                if (err != NGX_EADDRINUSE) {
553                    return NGX_ERROR;
554                }
555
556                if (!ngx_test_config) {
557                    failed = 1;
558                }
559
560                continue;
561            }
562
563#if (NGX_HAVE_UNIX_DOMAIN)
564
565            if (ls[i].sockaddr->sa_family == AF_UNIX) {
566                mode_t   mode;
567                u_char  *name;
568
569                name = ls[i].addr_text.data + sizeof("unix:") - 1;
570                mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
571
572                if (chmod((char *) name, mode) == -1) {
573                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
574                                  "chmod() \"%s\" failed", name);
575                }
576
577                if (ngx_test_config) {
578                    if (ngx_delete_file(name) == NGX_FILE_ERROR) {
579                        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
580                                      ngx_delete_file_n " %s failed", name);
581                    }
582                }
583            }
584#endif
585
586            if (ls[i].type != SOCK_STREAM) {
587                ls[i].fd = s;
588                continue;
589            }
590
591            if (listen(s, ls[i].backlog) == -1) {
592                err = ngx_socket_errno;
593
594                /*
595                 * on OpenVZ after suspend/resume EADDRINUSE
596                 * may be returned by listen() instead of bind(), see
597                 * https://bugzilla.openvz.org/show_bug.cgi?id=2470
598                 */
599
600                if (err != NGX_EADDRINUSE || !ngx_test_config) {
601                    ngx_log_error(NGX_LOG_EMERG, log, err,
602                                  "listen() to %V, backlog %d failed",
603                                  &ls[i].addr_text, ls[i].backlog);
604                }
605
606                if (ngx_close_socket(s) == -1) {
607                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
608                                  ngx_close_socket_n " %V failed",
609                                  &ls[i].addr_text);
610                }
611
612                if (err != NGX_EADDRINUSE) {
613                    return NGX_ERROR;
614                }
615
616                if (!ngx_test_config) {
617                    failed = 1;
618                }
619
620                continue;
621            }
622
623            ls[i].listen = 1;
624
625            ls[i].fd = s;
626        }
627
628        if (!failed) {
629            break;
630        }
631
632        /* TODO: delay configurable */
633
634        ngx_log_error(NGX_LOG_NOTICE, log, 0,
635                      "try again to bind() after 500ms");
636
637        ngx_msleep(500);
638    }
639
640    if (failed) {
641        ngx_log_error(NGX_LOG_EMERG, log, 0, "still could not bind()");
642        return NGX_ERROR;
643    }
644
645    return NGX_OK;
646}
647
648
649void
650ngx_configure_listening_sockets(ngx_cycle_t *cycle)
651{
652    int                        value;
653    ngx_uint_t                 i;
654    ngx_listening_t           *ls;
655
656#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
657    struct accept_filter_arg   af;
658#endif
659
660    ls = cycle->listening.elts;
661    for (i = 0; i < cycle->listening.nelts; i++) {
662
663        ls[i].log = *ls[i].logp;
664
665        if (ls[i].rcvbuf != -1) {
666            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF,
667                           (const void *) &ls[i].rcvbuf, sizeof(int))
668                == -1)
669            {
670                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
671                              "setsockopt(SO_RCVBUF, %d) %V failed, ignored",
672                              ls[i].rcvbuf, &ls[i].addr_text);
673            }
674        }
675
676        if (ls[i].sndbuf != -1) {
677            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF,
678                           (const void *) &ls[i].sndbuf, sizeof(int))
679                == -1)
680            {
681                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
682                              "setsockopt(SO_SNDBUF, %d) %V failed, ignored",
683                              ls[i].sndbuf, &ls[i].addr_text);
684            }
685        }
686
687        if (ls[i].keepalive) {
688            value = (ls[i].keepalive == 1) ? 1 : 0;
689
690            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,
691                           (const void *) &value, sizeof(int))
692                == -1)
693            {
694                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
695                              "setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",
696                              value, &ls[i].addr_text);
697            }
698        }
699
700#if (NGX_HAVE_KEEPALIVE_TUNABLE)
701
702        if (ls[i].keepidle) {
703            value = ls[i].keepidle;
704
705#if (NGX_KEEPALIVE_FACTOR)
706            value *= NGX_KEEPALIVE_FACTOR;
707#endif
708
709            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
710                           (const void *) &value, sizeof(int))
711                == -1)
712            {
713                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
714                              "setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
715                              value, &ls[i].addr_text);
716            }
717        }
718
719        if (ls[i].keepintvl) {
720            value = ls[i].keepintvl;
721
722#if (NGX_KEEPALIVE_FACTOR)
723            value *= NGX_KEEPALIVE_FACTOR;
724#endif
725
726            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
727                           (const void *) &value, sizeof(int))
728                == -1)
729            {
730                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
731                             "setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
732                             value, &ls[i].addr_text);
733            }
734        }
735
736        if (ls[i].keepcnt) {
737            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPCNT,
738                           (const void *) &ls[i].keepcnt, sizeof(int))
739                == -1)
740            {
741                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
742                              "setsockopt(TCP_KEEPCNT, %d) %V failed, ignored",
743                              ls[i].keepcnt, &ls[i].addr_text);
744            }
745        }
746
747#endif
748
749#if (NGX_HAVE_SETFIB)
750        if (ls[i].setfib != -1) {
751            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
752                           (const void *) &ls[i].setfib, sizeof(int))
753                == -1)
754            {
755                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
756                              "setsockopt(SO_SETFIB, %d) %V failed, ignored",
757                              ls[i].setfib, &ls[i].addr_text);
758            }
759        }
760#endif
761
762#if (NGX_HAVE_TCP_FASTOPEN)
763        if (ls[i].fastopen != -1) {
764            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
765                           (const void *) &ls[i].fastopen, sizeof(int))
766                == -1)
767            {
768                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
769                              "setsockopt(TCP_FASTOPEN, %d) %V failed, ignored",
770                              ls[i].fastopen, &ls[i].addr_text);
771            }
772        }
773#endif
774
775#if 0
776        if (1) {
777            int tcp_nodelay = 1;
778
779            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_NODELAY,
780                       (const void *) &tcp_nodelay, sizeof(int))
781                == -1)
782            {
783                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
784                              "setsockopt(TCP_NODELAY) %V failed, ignored",
785                              &ls[i].addr_text);
786            }
787        }
788#endif
789
790        if (ls[i].listen) {
791
792            /* change backlog via listen() */
793
794            if (listen(ls[i].fd, ls[i].backlog) == -1) {
795                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
796                              "listen() to %V, backlog %d failed, ignored",
797                              &ls[i].addr_text, ls[i].backlog);
798            }
799        }
800
801        /*
802         * setting deferred mode should be last operation on socket,
803         * because code may prematurely continue cycle on failure
804         */
805
806#if (NGX_HAVE_DEFERRED_ACCEPT)
807
808#ifdef SO_ACCEPTFILTER
809
810        if (ls[i].delete_deferred) {
811            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
812                == -1)
813            {
814                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
815                              "setsockopt(SO_ACCEPTFILTER, NULL) "
816                              "for %V failed, ignored",
817                              &ls[i].addr_text);
818
819                if (ls[i].accept_filter) {
820                    ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
821                                  "could not change the accept filter "
822                                  "to \"%s\" for %V, ignored",
823                                  ls[i].accept_filter, &ls[i].addr_text);
824                }
825
826                continue;
827            }
828
829            ls[i].deferred_accept = 0;
830        }
831
832        if (ls[i].add_deferred) {
833            ngx_memzero(&af, sizeof(struct accept_filter_arg));
834            (void) ngx_cpystrn((u_char *) af.af_name,
835                               (u_char *) ls[i].accept_filter, 16);
836
837            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER,
838                           &af, sizeof(struct accept_filter_arg))
839                == -1)
840            {
841                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
842                              "setsockopt(SO_ACCEPTFILTER, \"%s\") "
843                              "for %V failed, ignored",
844                              ls[i].accept_filter, &ls[i].addr_text);
845                continue;
846            }
847
848            ls[i].deferred_accept = 1;
849        }
850
851#endif
852
853#ifdef TCP_DEFER_ACCEPT
854
855        if (ls[i].add_deferred || ls[i].delete_deferred) {
856
857            if (ls[i].add_deferred) {
858                /*
859                 * There is no way to find out how long a connection was
860                 * in queue (and a connection may bypass deferred queue at all
861                 * if syncookies were used), hence we use 1 second timeout
862                 * here.
863                 */
864                value = 1;
865
866            } else {
867                value = 0;
868            }
869
870            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
871                           &value, sizeof(int))
872                == -1)
873            {
874                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
875                              "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
876                              "ignored",
877                              value, &ls[i].addr_text);
878
879                continue;
880            }
881        }
882
883        if (ls[i].add_deferred) {
884            ls[i].deferred_accept = 1;
885        }
886
887#endif
888
889#endif /* NGX_HAVE_DEFERRED_ACCEPT */
890
891#if (NGX_HAVE_IP_RECVDSTADDR)
892
893        if (ls[i].wildcard
894            && ls[i].type == SOCK_DGRAM
895            && ls[i].sockaddr->sa_family == AF_INET)
896        {
897            value = 1;
898
899            if (setsockopt(ls[i].fd, IPPROTO_IP, IP_RECVDSTADDR,
900                           (const void *) &value, sizeof(int))
901                == -1)
902            {
903                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
904                              "setsockopt(IP_RECVDSTADDR) "
905                              "for %V failed, ignored",
906                              &ls[i].addr_text);
907            }
908        }
909
910#elif (NGX_HAVE_IP_PKTINFO)
911
912        if (ls[i].wildcard
913            && ls[i].type == SOCK_DGRAM
914            && ls[i].sockaddr->sa_family == AF_INET)
915        {
916            value = 1;
917
918            if (setsockopt(ls[i].fd, IPPROTO_IP, IP_PKTINFO,
919                           (const void *) &value, sizeof(int))
920                == -1)
921            {
922                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
923                              "setsockopt(IP_PKTINFO) "
924                              "for %V failed, ignored",
925                              &ls[i].addr_text);
926            }
927        }
928
929#endif
930
931#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
932
933        if (ls[i].wildcard
934            && ls[i].type == SOCK_DGRAM
935            && ls[i].sockaddr->sa_family == AF_INET6)
936        {
937            value = 1;
938
939            if (setsockopt(ls[i].fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
940                           (const void *) &value, sizeof(int))
941                == -1)
942            {
943                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
944                              "setsockopt(IPV6_RECVPKTINFO) "
945                              "for %V failed, ignored",
946                              &ls[i].addr_text);
947            }
948        }
949
950#endif
951    }
952
953    return;
954}
955
956
957void
958ngx_close_listening_sockets(ngx_cycle_t *cycle)
959{
960    ngx_uint_t         i;
961    ngx_listening_t   *ls;
962    ngx_connection_t  *c;
963
964    if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
965        return;
966    }
967
968    ngx_accept_mutex_held = 0;
969    ngx_use_accept_mutex = 0;
970
971    ls = cycle->listening.elts;
972    for (i = 0; i < cycle->listening.nelts; i++) {
973
974        c = ls[i].connection;
975
976        if (c) {
977            if (c->read->active) {
978                if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
979
980                    /*
981                     * it seems that Linux-2.6.x OpenVZ sends events
982                     * for closed shared listening sockets unless
983                     * the events was explicitly deleted
984                     */
985
986                    ngx_del_event(c->read, NGX_READ_EVENT, 0);
987
988                } else {
989                    ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
990                }
991            }
992
993            ngx_free_connection(c);
994
995            c->fd = (ngx_socket_t) -1;
996        }
997
998        ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
999                       "close listening %V #%d ", &ls[i].addr_text, ls[i].fd);
1000
1001        if (ngx_close_socket(ls[i].fd) == -1) {
1002            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
1003                          ngx_close_socket_n " %V failed", &ls[i].addr_text);
1004        }
1005
1006#if (NGX_HAVE_UNIX_DOMAIN)
1007
1008        if (ls[i].sockaddr->sa_family == AF_UNIX
1009            && ngx_process <= NGX_PROCESS_MASTER
1010            && ngx_new_binary == 0)
1011        {
1012            u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
1013
1014            if (ngx_delete_file(name) == NGX_FILE_ERROR) {
1015                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
1016                              ngx_delete_file_n " %s failed", name);
1017            }
1018        }
1019
1020#endif
1021
1022        ls[i].fd = (ngx_socket_t) -1;
1023    }
1024
1025    cycle->listening.nelts = 0;
1026}
1027
1028
1029ngx_connection_t *
1030ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
1031{
1032    ngx_uint_t         instance;
1033    ngx_event_t       *rev, *wev;
1034    ngx_connection_t  *c;
1035
1036    /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
1037
1038    if (ngx_cycle->files && (ngx_uint_t) s >= ngx_cycle->files_n) {
1039        ngx_log_error(NGX_LOG_ALERT, log, 0,
1040                      "the new socket has number %d, "
1041                      "but only %ui files are available",
1042                      s, ngx_cycle->files_n);
1043        return NULL;
1044    }
1045
1046    c = ngx_cycle->free_connections;
1047
1048    if (c == NULL) {
1049        ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
1050        c = ngx_cycle->free_connections;
1051    }
1052
1053    if (c == NULL) {
1054        ngx_log_error(NGX_LOG_ALERT, log, 0,
1055                      "%ui worker_connections are not enough",
1056                      ngx_cycle->connection_n);
1057
1058        return NULL;
1059    }
1060
1061    ngx_cycle->free_connections = c->data;
1062    ngx_cycle->free_connection_n--;
1063
1064    if (ngx_cycle->files && ngx_cycle->files[s] == NULL) {
1065        ngx_cycle->files[s] = c;
1066    }
1067
1068    rev = c->read;
1069    wev = c->write;
1070
1071    ngx_memzero(c, sizeof(ngx_connection_t));
1072
1073    c->read = rev;
1074    c->write = wev;
1075    c->fd = s;
1076    c->log = log;
1077
1078    instance = rev->instance;
1079
1080    ngx_memzero(rev, sizeof(ngx_event_t));
1081    ngx_memzero(wev, sizeof(ngx_event_t));
1082
1083    rev->instance = !instance;
1084    wev->instance = !instance;
1085
1086    rev->index = NGX_INVALID_INDEX;
1087    wev->index = NGX_INVALID_INDEX;
1088
1089    rev->data = c;
1090    wev->data = c;
1091
1092    wev->write = 1;
1093
1094    return c;
1095}
1096
1097
1098void
1099ngx_free_connection(ngx_connection_t *c)
1100{
1101    c->data = ngx_cycle->free_connections;
1102    ngx_cycle->free_connections = c;
1103    ngx_cycle->free_connection_n++;
1104
1105    if (ngx_cycle->files && ngx_cycle->files[c->fd] == c) {
1106        ngx_cycle->files[c->fd] = NULL;
1107    }
1108}
1109
1110
1111void
1112ngx_close_connection(ngx_connection_t *c)
1113{
1114    ngx_err_t     err;
1115    ngx_uint_t    log_error, level;
1116    ngx_socket_t  fd;
1117
1118    if (c->fd == (ngx_socket_t) -1) {
1119        ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
1120        return;
1121    }
1122
1123    if (c->read->timer_set) {
1124        ngx_del_timer(c->read);
1125    }
1126
1127    if (c->write->timer_set) {
1128        ngx_del_timer(c->write);
1129    }
1130
1131    if (!c->shared) {
1132        if (ngx_del_conn) {
1133            ngx_del_conn(c, NGX_CLOSE_EVENT);
1134
1135        } else {
1136            if (c->read->active || c->read->disabled) {
1137                ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
1138            }
1139
1140            if (c->write->active || c->write->disabled) {
1141                ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
1142            }
1143        }
1144    }
1145
1146    if (c->read->posted) {
1147        ngx_delete_posted_event(c->read);
1148    }
1149
1150    if (c->write->posted) {
1151        ngx_delete_posted_event(c->write);
1152    }
1153
1154    c->read->closed = 1;
1155    c->write->closed = 1;
1156
1157    ngx_reusable_connection(c, 0);
1158
1159    log_error = c->log_error;
1160
1161    ngx_free_connection(c);
1162
1163    fd = c->fd;
1164    c->fd = (ngx_socket_t) -1;
1165
1166    if (c->shared) {
1167        return;
1168    }
1169
1170    if (ngx_close_socket(fd) == -1) {
1171
1172        err = ngx_socket_errno;
1173
1174        if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) {
1175
1176            switch (log_error) {
1177
1178            case NGX_ERROR_INFO:
1179                level = NGX_LOG_INFO;
1180                break;
1181
1182            case NGX_ERROR_ERR:
1183                level = NGX_LOG_ERR;
1184                break;
1185
1186            default:
1187                level = NGX_LOG_CRIT;
1188            }
1189
1190        } else {
1191            level = NGX_LOG_CRIT;
1192        }
1193
1194        ngx_log_error(level, c->log, err, ngx_close_socket_n " %d failed", fd);
1195    }
1196}
1197
1198
1199void
1200ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable)
1201{
1202    ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
1203                   "reusable connection: %ui", reusable);
1204
1205    if (c->reusable) {
1206        ngx_queue_remove(&c->queue);
1207        ngx_cycle->reusable_connections_n--;
1208
1209#if (NGX_STAT_STUB)
1210        (void) ngx_atomic_fetch_add(ngx_stat_waiting, -1);
1211#endif
1212    }
1213
1214    c->reusable = reusable;
1215
1216    if (reusable) {
1217        /* need cast as ngx_cycle is volatile */
1218
1219        ngx_queue_insert_head(
1220            (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue);
1221        ngx_cycle->reusable_connections_n++;
1222
1223#if (NGX_STAT_STUB)
1224        (void) ngx_atomic_fetch_add(ngx_stat_waiting, 1);
1225#endif
1226    }
1227}
1228
1229
1230static void
1231ngx_drain_connections(ngx_cycle_t *cycle)
1232{
1233    ngx_uint_t         i, n;
1234    ngx_queue_t       *q;
1235    ngx_connection_t  *c;
1236
1237    n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1);
1238
1239    for (i = 0; i < n; i++) {
1240        if (ngx_queue_empty(&cycle->reusable_connections_queue)) {
1241            break;
1242        }
1243
1244        q = ngx_queue_last(&cycle->reusable_connections_queue);
1245        c = ngx_queue_data(q, ngx_connection_t, queue);
1246
1247        ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
1248                       "reusing connection");
1249
1250        c->close = 1;
1251        c->read->handler(c->read);
1252    }
1253}
1254
1255
1256void
1257ngx_close_idle_connections(ngx_cycle_t *cycle)
1258{
1259    ngx_uint_t         i;
1260    ngx_connection_t  *c;
1261
1262    c = cycle->connections;
1263
1264    for (i = 0; i < cycle->connection_n; i++) {
1265
1266        /* THREAD: lock */
1267
1268        if (c[i].fd != (ngx_socket_t) -1 && c[i].idle) {
1269            c[i].close = 1;
1270            c[i].read->handler(c[i].read);
1271        }
1272    }
1273}
1274
1275
1276ngx_int_t
1277ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
1278    ngx_uint_t port)
1279{
1280    socklen_t             len;
1281    ngx_uint_t            addr;
1282    ngx_sockaddr_t        sa;
1283    struct sockaddr_in   *sin;
1284#if (NGX_HAVE_INET6)
1285    ngx_uint_t            i;
1286    struct sockaddr_in6  *sin6;
1287#endif
1288
1289    addr = 0;
1290
1291    if (c->local_socklen) {
1292        switch (c->local_sockaddr->sa_family) {
1293
1294#if (NGX_HAVE_INET6)
1295        case AF_INET6:
1296            sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
1297
1298            for (i = 0; addr == 0 && i < 16; i++) {
1299                addr |= sin6->sin6_addr.s6_addr[i];
1300            }
1301
1302            break;
1303#endif
1304
1305#if (NGX_HAVE_UNIX_DOMAIN)
1306        case AF_UNIX:
1307            addr = 1;
1308            break;
1309#endif
1310
1311        default: /* AF_INET */
1312            sin = (struct sockaddr_in *) c->local_sockaddr;
1313            addr = sin->sin_addr.s_addr;
1314            break;
1315        }
1316    }
1317
1318    if (addr == 0) {
1319
1320        len = sizeof(ngx_sockaddr_t);
1321
1322        if (getsockname(c->fd, &sa.sockaddr, &len) == -1) {
1323            ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
1324            return NGX_ERROR;
1325        }
1326
1327        c->local_sockaddr = ngx_palloc(c->pool, len);
1328        if (c->local_sockaddr == NULL) {
1329            return NGX_ERROR;
1330        }
1331
1332        ngx_memcpy(c->local_sockaddr, &sa, len);
1333
1334        c->local_socklen = len;
1335    }
1336
1337    if (s == NULL) {
1338        return NGX_OK;
1339    }
1340
1341    s->len = ngx_sock_ntop(c->local_sockaddr, c->local_socklen,
1342                           s->data, s->len, port);
1343
1344    return NGX_OK;
1345}
1346
1347
1348ngx_int_t
1349ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
1350{
1351    ngx_uint_t  level;
1352
1353    /* Winsock may return NGX_ECONNABORTED instead of NGX_ECONNRESET */
1354
1355    if ((err == NGX_ECONNRESET
1356#if (NGX_WIN32)
1357         || err == NGX_ECONNABORTED
1358#endif
1359        ) && c->log_error == NGX_ERROR_IGNORE_ECONNRESET)
1360    {
1361        return 0;
1362    }
1363
1364#if (NGX_SOLARIS)
1365    if (err == NGX_EINVAL && c->log_error == NGX_ERROR_IGNORE_EINVAL) {
1366        return 0;
1367    }
1368#endif
1369
1370    if (err == 0
1371        || err == NGX_ECONNRESET
1372#if (NGX_WIN32)
1373        || err == NGX_ECONNABORTED
1374#else
1375        || err == NGX_EPIPE
1376#endif
1377        || err == NGX_ENOTCONN
1378        || err == NGX_ETIMEDOUT
1379        || err == NGX_ECONNREFUSED
1380        || err == NGX_ENETDOWN
1381        || err == NGX_ENETUNREACH
1382        || err == NGX_EHOSTDOWN
1383        || err == NGX_EHOSTUNREACH)
1384    {
1385        switch (c->log_error) {
1386
1387        case NGX_ERROR_IGNORE_EINVAL:
1388        case NGX_ERROR_IGNORE_ECONNRESET:
1389        case NGX_ERROR_INFO:
1390            level = NGX_LOG_INFO;
1391            break;
1392
1393        default:
1394            level = NGX_LOG_ERR;
1395        }
1396
1397    } else {
1398        level = NGX_LOG_ALERT;
1399    }
1400
1401    ngx_log_error(level, c->log, err, text);
1402
1403    return NGX_ERROR;
1404}
1405