1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_event.h>
11e18a033bSKonstantin Ananyev#include <ngx_event_connect.h>
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyev
14e18a033bSKonstantin Ananyev#if (NGX_HAVE_TRANSPARENT_PROXY)
15e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_event_connect_set_transparent(ngx_peer_connection_t *pc,
16e18a033bSKonstantin Ananyev    ngx_socket_t s);
17e18a033bSKonstantin Ananyev#endif
18e18a033bSKonstantin Ananyev
19e18a033bSKonstantin Ananyev
20e18a033bSKonstantin Ananyevngx_int_t
21e18a033bSKonstantin Ananyevngx_event_connect_peer(ngx_peer_connection_t *pc)
22e18a033bSKonstantin Ananyev{
23e18a033bSKonstantin Ananyev    int                rc, type;
24e18a033bSKonstantin Ananyev#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT || NGX_LINUX)
25e18a033bSKonstantin Ananyev    in_port_t          port;
26e18a033bSKonstantin Ananyev#endif
27e18a033bSKonstantin Ananyev    ngx_int_t          event;
28e18a033bSKonstantin Ananyev    ngx_err_t          err;
29e18a033bSKonstantin Ananyev    ngx_uint_t         level;
30e18a033bSKonstantin Ananyev    ngx_socket_t       s;
31e18a033bSKonstantin Ananyev    ngx_event_t       *rev, *wev;
32e18a033bSKonstantin Ananyev    ngx_connection_t  *c;
33e18a033bSKonstantin Ananyev
34e18a033bSKonstantin Ananyev    rc = pc->get(pc, pc->data);
35e18a033bSKonstantin Ananyev    if (rc != NGX_OK) {
36e18a033bSKonstantin Ananyev        return rc;
37e18a033bSKonstantin Ananyev    }
38e18a033bSKonstantin Ananyev
39e18a033bSKonstantin Ananyev    type = (pc->type ? pc->type : SOCK_STREAM);
40e18a033bSKonstantin Ananyev
41e18a033bSKonstantin Ananyev    s = ngx_socket(pc->sockaddr->sa_family, type, 0);
42e18a033bSKonstantin Ananyev
43e18a033bSKonstantin Ananyev    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pc->log, 0, "%s socket %d",
44e18a033bSKonstantin Ananyev                   (type == SOCK_STREAM) ? "stream" : "dgram", s);
45e18a033bSKonstantin Ananyev
46e18a033bSKonstantin Ananyev    if (s == (ngx_socket_t) -1) {
47e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
48e18a033bSKonstantin Ananyev                      ngx_socket_n " failed");
49e18a033bSKonstantin Ananyev        return NGX_ERROR;
50e18a033bSKonstantin Ananyev    }
51e18a033bSKonstantin Ananyev
52e18a033bSKonstantin Ananyev
53e18a033bSKonstantin Ananyev    c = ngx_get_connection(s, pc->log);
54e18a033bSKonstantin Ananyev
55e18a033bSKonstantin Ananyev    if (c == NULL) {
56e18a033bSKonstantin Ananyev        if (ngx_close_socket(s) == -1) {
57e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
58e18a033bSKonstantin Ananyev                          ngx_close_socket_n "failed");
59e18a033bSKonstantin Ananyev        }
60e18a033bSKonstantin Ananyev
61e18a033bSKonstantin Ananyev        return NGX_ERROR;
62e18a033bSKonstantin Ananyev    }
63e18a033bSKonstantin Ananyev
64e18a033bSKonstantin Ananyev    c->type = type;
65e18a033bSKonstantin Ananyev
66e18a033bSKonstantin Ananyev    if (pc->rcvbuf) {
67e18a033bSKonstantin Ananyev        if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
68e18a033bSKonstantin Ananyev                       (const void *) &pc->rcvbuf, sizeof(int)) == -1)
69e18a033bSKonstantin Ananyev        {
70e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
71e18a033bSKonstantin Ananyev                          "setsockopt(SO_RCVBUF) failed");
72e18a033bSKonstantin Ananyev            goto failed;
73e18a033bSKonstantin Ananyev        }
74e18a033bSKonstantin Ananyev    }
75e18a033bSKonstantin Ananyev
76e18a033bSKonstantin Ananyev    if (ngx_nonblocking(s) == -1) {
77e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
78e18a033bSKonstantin Ananyev                      ngx_nonblocking_n " failed");
79e18a033bSKonstantin Ananyev
80e18a033bSKonstantin Ananyev        goto failed;
81e18a033bSKonstantin Ananyev    }
82e18a033bSKonstantin Ananyev
83e18a033bSKonstantin Ananyev    if (pc->local) {
84e18a033bSKonstantin Ananyev
85e18a033bSKonstantin Ananyev#if (NGX_HAVE_TRANSPARENT_PROXY)
86e18a033bSKonstantin Ananyev        if (pc->transparent) {
87e18a033bSKonstantin Ananyev            if (ngx_event_connect_set_transparent(pc, s) != NGX_OK) {
88e18a033bSKonstantin Ananyev                goto failed;
89e18a033bSKonstantin Ananyev            }
90e18a033bSKonstantin Ananyev        }
91e18a033bSKonstantin Ananyev#endif
92e18a033bSKonstantin Ananyev
93e18a033bSKonstantin Ananyev#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT || NGX_LINUX)
94e18a033bSKonstantin Ananyev        port = ngx_inet_get_port(pc->local->sockaddr);
95e18a033bSKonstantin Ananyev#endif
96e18a033bSKonstantin Ananyev
97e18a033bSKonstantin Ananyev#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT)
98e18a033bSKonstantin Ananyev
99e18a033bSKonstantin Ananyev        if (pc->sockaddr->sa_family != AF_UNIX && port == 0) {
100e18a033bSKonstantin Ananyev            static int  bind_address_no_port = 1;
101e18a033bSKonstantin Ananyev
102e18a033bSKonstantin Ananyev            if (bind_address_no_port) {
103e18a033bSKonstantin Ananyev                if (setsockopt(s, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT,
104e18a033bSKonstantin Ananyev                               (const void *) &bind_address_no_port,
105e18a033bSKonstantin Ananyev                               sizeof(int)) == -1)
106e18a033bSKonstantin Ananyev                {
107e18a033bSKonstantin Ananyev                    err = ngx_socket_errno;
108e18a033bSKonstantin Ananyev
109e18a033bSKonstantin Ananyev                    if (err != NGX_EOPNOTSUPP && err != NGX_ENOPROTOOPT) {
110e18a033bSKonstantin Ananyev                        ngx_log_error(NGX_LOG_ALERT, pc->log, err,
111e18a033bSKonstantin Ananyev                                      "setsockopt(IP_BIND_ADDRESS_NO_PORT) "
112e18a033bSKonstantin Ananyev                                      "failed, ignored");
113e18a033bSKonstantin Ananyev
114e18a033bSKonstantin Ananyev                    } else {
115e18a033bSKonstantin Ananyev                        bind_address_no_port = 0;
116e18a033bSKonstantin Ananyev                    }
117e18a033bSKonstantin Ananyev                }
118e18a033bSKonstantin Ananyev            }
119e18a033bSKonstantin Ananyev        }
120e18a033bSKonstantin Ananyev
121e18a033bSKonstantin Ananyev#endif
122e18a033bSKonstantin Ananyev
123e18a033bSKonstantin Ananyev#if (NGX_LINUX)
124e18a033bSKonstantin Ananyev
125e18a033bSKonstantin Ananyev        if (pc->type == SOCK_DGRAM && port != 0) {
126e18a033bSKonstantin Ananyev            int  reuse_addr = 1;
127e18a033bSKonstantin Ananyev
128e18a033bSKonstantin Ananyev            if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
129e18a033bSKonstantin Ananyev                           (const void *) &reuse_addr, sizeof(int))
130e18a033bSKonstantin Ananyev                 == -1)
131e18a033bSKonstantin Ananyev            {
132e18a033bSKonstantin Ananyev                ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
133e18a033bSKonstantin Ananyev                              "setsockopt(SO_REUSEADDR) failed");
134e18a033bSKonstantin Ananyev                goto failed;
135e18a033bSKonstantin Ananyev            }
136e18a033bSKonstantin Ananyev        }
137e18a033bSKonstantin Ananyev
138e18a033bSKonstantin Ananyev#endif
139e18a033bSKonstantin Ananyev
140e18a033bSKonstantin Ananyev        if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) {
141e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno,
142e18a033bSKonstantin Ananyev                          "bind(%V) failed", &pc->local->name);
143e18a033bSKonstantin Ananyev
144e18a033bSKonstantin Ananyev            goto failed;
145e18a033bSKonstantin Ananyev        }
146e18a033bSKonstantin Ananyev    }
147e18a033bSKonstantin Ananyev
148e18a033bSKonstantin Ananyev    if (type == SOCK_STREAM) {
149e18a033bSKonstantin Ananyev        c->recv = ngx_recv;
150e18a033bSKonstantin Ananyev        c->send = ngx_send;
151e18a033bSKonstantin Ananyev        c->recv_chain = ngx_recv_chain;
152e18a033bSKonstantin Ananyev        c->send_chain = ngx_send_chain;
153e18a033bSKonstantin Ananyev
154e18a033bSKonstantin Ananyev        c->sendfile = 1;
155e18a033bSKonstantin Ananyev
156e18a033bSKonstantin Ananyev        if (pc->sockaddr->sa_family == AF_UNIX) {
157e18a033bSKonstantin Ananyev            c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
158e18a033bSKonstantin Ananyev            c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
159e18a033bSKonstantin Ananyev
160e18a033bSKonstantin Ananyev#if (NGX_SOLARIS)
161e18a033bSKonstantin Ananyev            /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
162e18a033bSKonstantin Ananyev            c->sendfile = 0;
163e18a033bSKonstantin Ananyev#endif
164e18a033bSKonstantin Ananyev        }
165e18a033bSKonstantin Ananyev
166e18a033bSKonstantin Ananyev    } else { /* type == SOCK_DGRAM */
167e18a033bSKonstantin Ananyev        c->recv = ngx_udp_recv;
168e18a033bSKonstantin Ananyev        c->send = ngx_send;
169e18a033bSKonstantin Ananyev        c->send_chain = ngx_udp_send_chain;
170e18a033bSKonstantin Ananyev    }
171e18a033bSKonstantin Ananyev
172e18a033bSKonstantin Ananyev    c->log_error = pc->log_error;
173e18a033bSKonstantin Ananyev
174e18a033bSKonstantin Ananyev    rev = c->read;
175e18a033bSKonstantin Ananyev    wev = c->write;
176e18a033bSKonstantin Ananyev
177e18a033bSKonstantin Ananyev    rev->log = pc->log;
178e18a033bSKonstantin Ananyev    wev->log = pc->log;
179e18a033bSKonstantin Ananyev
180e18a033bSKonstantin Ananyev    pc->connection = c;
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev    c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
183e18a033bSKonstantin Ananyev
184e18a033bSKonstantin Ananyev    if (ngx_add_conn) {
185e18a033bSKonstantin Ananyev        if (ngx_add_conn(c) == NGX_ERROR) {
186e18a033bSKonstantin Ananyev            goto failed;
187e18a033bSKonstantin Ananyev        }
188e18a033bSKonstantin Ananyev    }
189e18a033bSKonstantin Ananyev
190e18a033bSKonstantin Ananyev    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pc->log, 0,
191e18a033bSKonstantin Ananyev                   "connect to %V, fd:%d #%uA", pc->name, s, c->number);
192e18a033bSKonstantin Ananyev
193e18a033bSKonstantin Ananyev    rc = connect(s, pc->sockaddr, pc->socklen);
194e18a033bSKonstantin Ananyev
195e18a033bSKonstantin Ananyev    if (rc == -1) {
196e18a033bSKonstantin Ananyev        err = ngx_socket_errno;
197e18a033bSKonstantin Ananyev
198e18a033bSKonstantin Ananyev
199e18a033bSKonstantin Ananyev        if (err != NGX_EINPROGRESS
200e18a033bSKonstantin Ananyev#if (NGX_WIN32)
201e18a033bSKonstantin Ananyev            /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */
202e18a033bSKonstantin Ananyev            && err != NGX_EAGAIN
203e18a033bSKonstantin Ananyev#endif
204e18a033bSKonstantin Ananyev            )
205e18a033bSKonstantin Ananyev        {
206e18a033bSKonstantin Ananyev            if (err == NGX_ECONNREFUSED
207e18a033bSKonstantin Ananyev#if (NGX_LINUX)
208e18a033bSKonstantin Ananyev                /*
209e18a033bSKonstantin Ananyev                 * Linux returns EAGAIN instead of ECONNREFUSED
210e18a033bSKonstantin Ananyev                 * for unix sockets if listen queue is full
211e18a033bSKonstantin Ananyev                 */
212e18a033bSKonstantin Ananyev                || err == NGX_EAGAIN
213e18a033bSKonstantin Ananyev#endif
214e18a033bSKonstantin Ananyev                || err == NGX_ECONNRESET
215e18a033bSKonstantin Ananyev                || err == NGX_ENETDOWN
216e18a033bSKonstantin Ananyev                || err == NGX_ENETUNREACH
217e18a033bSKonstantin Ananyev                || err == NGX_EHOSTDOWN
218e18a033bSKonstantin Ananyev                || err == NGX_EHOSTUNREACH)
219e18a033bSKonstantin Ananyev            {
220e18a033bSKonstantin Ananyev                level = NGX_LOG_ERR;
221e18a033bSKonstantin Ananyev
222e18a033bSKonstantin Ananyev            } else {
223e18a033bSKonstantin Ananyev                level = NGX_LOG_CRIT;
224e18a033bSKonstantin Ananyev            }
225e18a033bSKonstantin Ananyev
226e18a033bSKonstantin Ananyev            ngx_log_error(level, c->log, err, "connect() to %V failed",
227e18a033bSKonstantin Ananyev                          pc->name);
228e18a033bSKonstantin Ananyev
229e18a033bSKonstantin Ananyev            ngx_close_connection(c);
230e18a033bSKonstantin Ananyev            pc->connection = NULL;
231e18a033bSKonstantin Ananyev
232e18a033bSKonstantin Ananyev            return NGX_DECLINED;
233e18a033bSKonstantin Ananyev        }
234e18a033bSKonstantin Ananyev    }
235e18a033bSKonstantin Ananyev
236e18a033bSKonstantin Ananyev    if (ngx_add_conn) {
237e18a033bSKonstantin Ananyev        if (rc == -1) {
238e18a033bSKonstantin Ananyev
239e18a033bSKonstantin Ananyev            /* NGX_EINPROGRESS */
240e18a033bSKonstantin Ananyev
241e18a033bSKonstantin Ananyev            return NGX_AGAIN;
242e18a033bSKonstantin Ananyev        }
243e18a033bSKonstantin Ananyev
244e18a033bSKonstantin Ananyev        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, pc->log, 0, "connected");
245e18a033bSKonstantin Ananyev
246e18a033bSKonstantin Ananyev        wev->ready = 1;
247e18a033bSKonstantin Ananyev
248e18a033bSKonstantin Ananyev        return NGX_OK;
249e18a033bSKonstantin Ananyev    }
250e18a033bSKonstantin Ananyev
251e18a033bSKonstantin Ananyev    if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
252e18a033bSKonstantin Ananyev
253e18a033bSKonstantin Ananyev        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, ngx_socket_errno,
254e18a033bSKonstantin Ananyev                       "connect(): %d", rc);
255e18a033bSKonstantin Ananyev
256e18a033bSKonstantin Ananyev        if (ngx_blocking(s) == -1) {
257e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
258e18a033bSKonstantin Ananyev                          ngx_blocking_n " failed");
259e18a033bSKonstantin Ananyev            goto failed;
260e18a033bSKonstantin Ananyev        }
261e18a033bSKonstantin Ananyev
262e18a033bSKonstantin Ananyev        /*
263e18a033bSKonstantin Ananyev         * FreeBSD's aio allows to post an operation on non-connected socket.
264e18a033bSKonstantin Ananyev         * NT does not support it.
265e18a033bSKonstantin Ananyev         *
266e18a033bSKonstantin Ananyev         * TODO: check in Win32, etc. As workaround we can use NGX_ONESHOT_EVENT
267e18a033bSKonstantin Ananyev         */
268e18a033bSKonstantin Ananyev
269e18a033bSKonstantin Ananyev        rev->ready = 1;
270e18a033bSKonstantin Ananyev        wev->ready = 1;
271e18a033bSKonstantin Ananyev
272e18a033bSKonstantin Ananyev        return NGX_OK;
273e18a033bSKonstantin Ananyev    }
274e18a033bSKonstantin Ananyev
275e18a033bSKonstantin Ananyev    if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
276e18a033bSKonstantin Ananyev
277e18a033bSKonstantin Ananyev        /* kqueue */
278e18a033bSKonstantin Ananyev
279e18a033bSKonstantin Ananyev        event = NGX_CLEAR_EVENT;
280e18a033bSKonstantin Ananyev
281e18a033bSKonstantin Ananyev    } else {
282e18a033bSKonstantin Ananyev
283e18a033bSKonstantin Ananyev        /* select, poll, /dev/poll */
284e18a033bSKonstantin Ananyev
285e18a033bSKonstantin Ananyev        event = NGX_LEVEL_EVENT;
286e18a033bSKonstantin Ananyev    }
287e18a033bSKonstantin Ananyev
288e18a033bSKonstantin Ananyev    if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
289e18a033bSKonstantin Ananyev        goto failed;
290e18a033bSKonstantin Ananyev    }
291e18a033bSKonstantin Ananyev
292e18a033bSKonstantin Ananyev    if (rc == -1) {
293e18a033bSKonstantin Ananyev
294e18a033bSKonstantin Ananyev        /* NGX_EINPROGRESS */
295e18a033bSKonstantin Ananyev
296e18a033bSKonstantin Ananyev        if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) {
297e18a033bSKonstantin Ananyev            goto failed;
298e18a033bSKonstantin Ananyev        }
299e18a033bSKonstantin Ananyev
300e18a033bSKonstantin Ananyev        return NGX_AGAIN;
301e18a033bSKonstantin Ananyev    }
302e18a033bSKonstantin Ananyev
303e18a033bSKonstantin Ananyev    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, pc->log, 0, "connected");
304e18a033bSKonstantin Ananyev
305e18a033bSKonstantin Ananyev    wev->ready = 1;
306e18a033bSKonstantin Ananyev
307e18a033bSKonstantin Ananyev    return NGX_OK;
308e18a033bSKonstantin Ananyev
309e18a033bSKonstantin Ananyevfailed:
310e18a033bSKonstantin Ananyev
311e18a033bSKonstantin Ananyev    ngx_close_connection(c);
312e18a033bSKonstantin Ananyev    pc->connection = NULL;
313e18a033bSKonstantin Ananyev
314e18a033bSKonstantin Ananyev    return NGX_ERROR;
315e18a033bSKonstantin Ananyev}
316e18a033bSKonstantin Ananyev
317e18a033bSKonstantin Ananyev
318e18a033bSKonstantin Ananyev#if (NGX_HAVE_TRANSPARENT_PROXY)
319e18a033bSKonstantin Ananyev
320e18a033bSKonstantin Ananyevstatic ngx_int_t
321e18a033bSKonstantin Ananyevngx_event_connect_set_transparent(ngx_peer_connection_t *pc, ngx_socket_t s)
322e18a033bSKonstantin Ananyev{
323e18a033bSKonstantin Ananyev    int  value;
324e18a033bSKonstantin Ananyev
325e18a033bSKonstantin Ananyev    value = 1;
326e18a033bSKonstantin Ananyev
327e18a033bSKonstantin Ananyev#if defined(SO_BINDANY)
328e18a033bSKonstantin Ananyev
329e18a033bSKonstantin Ananyev    if (setsockopt(s, SOL_SOCKET, SO_BINDANY,
330e18a033bSKonstantin Ananyev                   (const void *) &value, sizeof(int)) == -1)
331e18a033bSKonstantin Ananyev    {
332e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
333e18a033bSKonstantin Ananyev                      "setsockopt(SO_BINDANY) failed");
334e18a033bSKonstantin Ananyev        return NGX_ERROR;
335e18a033bSKonstantin Ananyev    }
336e18a033bSKonstantin Ananyev
337e18a033bSKonstantin Ananyev#else
338e18a033bSKonstantin Ananyev
339e18a033bSKonstantin Ananyev    switch (pc->local->sockaddr->sa_family) {
340e18a033bSKonstantin Ananyev
341e18a033bSKonstantin Ananyev    case AF_INET:
342e18a033bSKonstantin Ananyev
343e18a033bSKonstantin Ananyev#if defined(IP_TRANSPARENT)
344e18a033bSKonstantin Ananyev
345e18a033bSKonstantin Ananyev        if (setsockopt(s, IPPROTO_IP, IP_TRANSPARENT,
346e18a033bSKonstantin Ananyev                       (const void *) &value, sizeof(int)) == -1)
347e18a033bSKonstantin Ananyev        {
348e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
349e18a033bSKonstantin Ananyev                          "setsockopt(IP_TRANSPARENT) failed");
350e18a033bSKonstantin Ananyev            return NGX_ERROR;
351e18a033bSKonstantin Ananyev        }
352e18a033bSKonstantin Ananyev
353e18a033bSKonstantin Ananyev#elif defined(IP_BINDANY)
354e18a033bSKonstantin Ananyev
355e18a033bSKonstantin Ananyev        if (setsockopt(s, IPPROTO_IP, IP_BINDANY,
356e18a033bSKonstantin Ananyev                       (const void *) &value, sizeof(int)) == -1)
357e18a033bSKonstantin Ananyev        {
358e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
359e18a033bSKonstantin Ananyev                          "setsockopt(IP_BINDANY) failed");
360e18a033bSKonstantin Ananyev            return NGX_ERROR;
361e18a033bSKonstantin Ananyev        }
362e18a033bSKonstantin Ananyev
363e18a033bSKonstantin Ananyev#endif
364e18a033bSKonstantin Ananyev
365e18a033bSKonstantin Ananyev        break;
366e18a033bSKonstantin Ananyev
367e18a033bSKonstantin Ananyev#if (NGX_HAVE_INET6)
368e18a033bSKonstantin Ananyev
369e18a033bSKonstantin Ananyev    case AF_INET6:
370e18a033bSKonstantin Ananyev
371e18a033bSKonstantin Ananyev#if defined(IPV6_TRANSPARENT)
372e18a033bSKonstantin Ananyev
373e18a033bSKonstantin Ananyev        if (setsockopt(s, IPPROTO_IPV6, IPV6_TRANSPARENT,
374e18a033bSKonstantin Ananyev                       (const void *) &value, sizeof(int)) == -1)
375e18a033bSKonstantin Ananyev        {
376e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
377e18a033bSKonstantin Ananyev                          "setsockopt(IPV6_TRANSPARENT) failed");
378e18a033bSKonstantin Ananyev            return NGX_ERROR;
379e18a033bSKonstantin Ananyev        }
380e18a033bSKonstantin Ananyev
381e18a033bSKonstantin Ananyev#elif defined(IPV6_BINDANY)
382e18a033bSKonstantin Ananyev
383e18a033bSKonstantin Ananyev        if (setsockopt(s, IPPROTO_IPV6, IPV6_BINDANY,
384e18a033bSKonstantin Ananyev                       (const void *) &value, sizeof(int)) == -1)
385e18a033bSKonstantin Ananyev        {
386e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
387e18a033bSKonstantin Ananyev                          "setsockopt(IPV6_BINDANY) failed");
388e18a033bSKonstantin Ananyev            return NGX_ERROR;
389e18a033bSKonstantin Ananyev        }
390e18a033bSKonstantin Ananyev
391e18a033bSKonstantin Ananyev#endif
392e18a033bSKonstantin Ananyev        break;
393e18a033bSKonstantin Ananyev
394e18a033bSKonstantin Ananyev#endif /* NGX_HAVE_INET6 */
395e18a033bSKonstantin Ananyev
396e18a033bSKonstantin Ananyev    }
397e18a033bSKonstantin Ananyev
398e18a033bSKonstantin Ananyev#endif /* SO_BINDANY */
399e18a033bSKonstantin Ananyev
400e18a033bSKonstantin Ananyev    return NGX_OK;
401e18a033bSKonstantin Ananyev}
402e18a033bSKonstantin Ananyev
403e18a033bSKonstantin Ananyev#endif
404e18a033bSKonstantin Ananyev
405e18a033bSKonstantin Ananyev
406e18a033bSKonstantin Ananyevngx_int_t
407e18a033bSKonstantin Ananyevngx_event_get_peer(ngx_peer_connection_t *pc, void *data)
408e18a033bSKonstantin Ananyev{
409e18a033bSKonstantin Ananyev    return NGX_OK;
410e18a033bSKonstantin Ananyev}
411