Mercurial > hg > nginx
annotate src/os/unix/ngx_udp_sendmsg_chain.c @ 9201:791ead216b03
Silenced complaints about socket leaks on forced termination.
When graceful shutdown was requested, and then nginx was forced to
do fast shutdown, it used to (incorrectly) complain about open sockets
left in connections which weren't yet closed when fast shutdown
was requested.
Fix is to avoid complaining about open sockets when fast shutdown was
requested after graceful one. Abnormal termination, if requested with
the WINCH signal, can still happen though.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 29 Jan 2024 10:29:39 +0300 |
parents | af5adec171b4 |
children |
rev | line source |
---|---|
6692 | 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 | |
13 static ngx_chain_t *ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec, | |
14 ngx_chain_t *in, ngx_log_t *log); | |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
15 static ssize_t ngx_sendmsg_vec(ngx_connection_t *c, ngx_iovec_t *vec); |
6692 | 16 |
17 | |
18 ngx_chain_t * | |
19 ngx_udp_unix_sendmsg_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) | |
20 { | |
21 ssize_t n; | |
22 off_t send; | |
23 ngx_chain_t *cl; | |
24 ngx_event_t *wev; | |
25 ngx_iovec_t vec; | |
26 struct iovec iovs[NGX_IOVS_PREALLOCATE]; | |
27 | |
28 wev = c->write; | |
29 | |
30 if (!wev->ready) { | |
31 return in; | |
32 } | |
33 | |
34 #if (NGX_HAVE_KQUEUE) | |
35 | |
36 if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { | |
37 (void) ngx_connection_error(c, wev->kq_errno, | |
38 "kevent() reported about an closed connection"); | |
39 wev->error = 1; | |
40 return NGX_CHAIN_ERROR; | |
41 } | |
42 | |
43 #endif | |
44 | |
45 /* the maximum limit size is the maximum size_t value - the page size */ | |
46 | |
47 if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { | |
48 limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; | |
49 } | |
50 | |
51 send = 0; | |
52 | |
53 vec.iovs = iovs; | |
54 vec.nalloc = NGX_IOVS_PREALLOCATE; | |
55 | |
56 for ( ;; ) { | |
57 | |
58 /* create the iovec and coalesce the neighbouring bufs */ | |
59 | |
60 cl = ngx_udp_output_chain_to_iovec(&vec, in, c->log); | |
61 | |
62 if (cl == NGX_CHAIN_ERROR) { | |
63 return NGX_CHAIN_ERROR; | |
64 } | |
65 | |
66 if (cl && cl->buf->in_file) { | |
67 ngx_log_error(NGX_LOG_ALERT, c->log, 0, | |
68 "file buf in sendmsg " | |
69 "t:%d r:%d f:%d %p %p-%p %p %O-%O", | |
70 cl->buf->temporary, | |
71 cl->buf->recycled, | |
72 cl->buf->in_file, | |
73 cl->buf->start, | |
74 cl->buf->pos, | |
75 cl->buf->last, | |
76 cl->buf->file, | |
77 cl->buf->file_pos, | |
78 cl->buf->file_last); | |
79 | |
80 ngx_debug_point(); | |
81 | |
82 return NGX_CHAIN_ERROR; | |
83 } | |
84 | |
85 if (cl == in) { | |
86 return in; | |
87 } | |
88 | |
89 send += vec.size; | |
90 | |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
91 n = ngx_sendmsg_vec(c, &vec); |
6692 | 92 |
93 if (n == NGX_ERROR) { | |
94 return NGX_CHAIN_ERROR; | |
95 } | |
96 | |
97 if (n == NGX_AGAIN) { | |
98 wev->ready = 0; | |
99 return in; | |
100 } | |
101 | |
102 c->sent += n; | |
103 | |
104 in = ngx_chain_update_sent(in, n); | |
105 | |
106 if (send >= limit || in == NULL) { | |
107 return in; | |
108 } | |
109 } | |
110 } | |
111 | |
112 | |
113 static ngx_chain_t * | |
114 ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *in, ngx_log_t *log) | |
115 { | |
116 size_t total, size; | |
117 u_char *prev; | |
118 ngx_uint_t n, flush; | |
119 ngx_chain_t *cl; | |
120 struct iovec *iov; | |
121 | |
122 cl = in; | |
123 iov = NULL; | |
124 prev = NULL; | |
125 total = 0; | |
126 n = 0; | |
127 flush = 0; | |
128 | |
129 for ( /* void */ ; in && !flush; in = in->next) { | |
130 | |
131 if (in->buf->flush || in->buf->last_buf) { | |
132 flush = 1; | |
133 } | |
134 | |
135 if (ngx_buf_special(in->buf)) { | |
136 continue; | |
137 } | |
138 | |
139 if (in->buf->in_file) { | |
140 break; | |
141 } | |
142 | |
143 if (!ngx_buf_in_memory(in->buf)) { | |
144 ngx_log_error(NGX_LOG_ALERT, log, 0, | |
145 "bad buf in output chain " | |
146 "t:%d r:%d f:%d %p %p-%p %p %O-%O", | |
147 in->buf->temporary, | |
148 in->buf->recycled, | |
149 in->buf->in_file, | |
150 in->buf->start, | |
151 in->buf->pos, | |
152 in->buf->last, | |
153 in->buf->file, | |
154 in->buf->file_pos, | |
155 in->buf->file_last); | |
156 | |
157 ngx_debug_point(); | |
158 | |
159 return NGX_CHAIN_ERROR; | |
160 } | |
161 | |
162 size = in->buf->last - in->buf->pos; | |
163 | |
164 if (prev == in->buf->pos) { | |
165 iov->iov_len += size; | |
166 | |
167 } else { | |
168 if (n == vec->nalloc) { | |
169 ngx_log_error(NGX_LOG_ALERT, log, 0, | |
170 "too many parts in a datagram"); | |
171 return NGX_CHAIN_ERROR; | |
172 } | |
173 | |
174 iov = &vec->iovs[n++]; | |
175 | |
176 iov->iov_base = (void *) in->buf->pos; | |
177 iov->iov_len = size; | |
178 } | |
179 | |
180 prev = in->buf->pos + size; | |
181 total += size; | |
182 } | |
183 | |
184 if (!flush) { | |
185 #if (NGX_SUPPRESS_WARN) | |
186 vec->size = 0; | |
187 vec->count = 0; | |
188 #endif | |
189 return cl; | |
190 } | |
191 | |
7665
d127837c714f
Stream: fixed processing of zero length UDP packets (ticket #1982).
Vladimir Homutov <vl@nginx.com>
parents:
7019
diff
changeset
|
192 /* zero-sized datagram; pretend to have at least 1 iov */ |
d127837c714f
Stream: fixed processing of zero length UDP packets (ticket #1982).
Vladimir Homutov <vl@nginx.com>
parents:
7019
diff
changeset
|
193 if (n == 0) { |
d127837c714f
Stream: fixed processing of zero length UDP packets (ticket #1982).
Vladimir Homutov <vl@nginx.com>
parents:
7019
diff
changeset
|
194 iov = &vec->iovs[n++]; |
d127837c714f
Stream: fixed processing of zero length UDP packets (ticket #1982).
Vladimir Homutov <vl@nginx.com>
parents:
7019
diff
changeset
|
195 iov->iov_base = NULL; |
d127837c714f
Stream: fixed processing of zero length UDP packets (ticket #1982).
Vladimir Homutov <vl@nginx.com>
parents:
7019
diff
changeset
|
196 iov->iov_len = 0; |
d127837c714f
Stream: fixed processing of zero length UDP packets (ticket #1982).
Vladimir Homutov <vl@nginx.com>
parents:
7019
diff
changeset
|
197 } |
d127837c714f
Stream: fixed processing of zero length UDP packets (ticket #1982).
Vladimir Homutov <vl@nginx.com>
parents:
7019
diff
changeset
|
198 |
6692 | 199 vec->count = n; |
200 vec->size = total; | |
201 | |
202 return in; | |
203 } | |
204 | |
205 | |
206 static ssize_t | |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
207 ngx_sendmsg_vec(ngx_connection_t *c, ngx_iovec_t *vec) |
6692 | 208 { |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
209 struct msghdr msg; |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
210 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
211 #if (NGX_HAVE_ADDRINFO_CMSG) |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
212 struct cmsghdr *cmsg; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
213 u_char msg_control[CMSG_SPACE(sizeof(ngx_addrinfo_t))]; |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
214 #endif |
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
215 |
6692 | 216 ngx_memzero(&msg, sizeof(struct msghdr)); |
217 | |
218 if (c->socklen) { | |
219 msg.msg_name = c->sockaddr; | |
220 msg.msg_namelen = c->socklen; | |
221 } | |
222 | |
223 msg.msg_iov = vec->iovs; | |
224 msg.msg_iovlen = vec->count; | |
225 | |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
226 #if (NGX_HAVE_ADDRINFO_CMSG) |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
227 if (c->listening && c->listening->wildcard && c->local_sockaddr) { |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
228 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
229 msg.msg_control = msg_control; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
230 msg.msg_controllen = sizeof(msg_control); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
231 ngx_memzero(msg_control, sizeof(msg_control)); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
232 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
233 cmsg = CMSG_FIRSTHDR(&msg); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
234 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
235 msg.msg_controllen = ngx_set_srcaddr_cmsg(cmsg, c->local_sockaddr); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
236 } |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
237 #endif |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
238 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
239 return ngx_sendmsg(c, &msg, 0); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
240 } |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
241 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
242 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
243 #if (NGX_HAVE_ADDRINFO_CMSG) |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
244 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
245 size_t |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
246 ngx_set_srcaddr_cmsg(struct cmsghdr *cmsg, struct sockaddr *local_sockaddr) |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
247 { |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
248 size_t len; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
249 #if (NGX_HAVE_IP_SENDSRCADDR) |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
250 struct in_addr *addr; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
251 struct sockaddr_in *sin; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
252 #elif (NGX_HAVE_IP_PKTINFO) |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
253 struct in_pktinfo *pkt; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
254 struct sockaddr_in *sin; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
255 #endif |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
256 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
257 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
258 struct in6_pktinfo *pkt6; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
259 struct sockaddr_in6 *sin6; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
260 #endif |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
261 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
262 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
263 #if (NGX_HAVE_IP_SENDSRCADDR) || (NGX_HAVE_IP_PKTINFO) |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
264 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
265 if (local_sockaddr->sa_family == AF_INET) { |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
266 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
267 cmsg->cmsg_level = IPPROTO_IP; |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
268 |
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
269 #if (NGX_HAVE_IP_SENDSRCADDR) |
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
270 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
271 cmsg->cmsg_type = IP_SENDSRCADDR; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
272 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
273 len = CMSG_SPACE(sizeof(struct in_addr)); |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
274 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
275 sin = (struct sockaddr_in *) local_sockaddr; |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
276 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
277 addr = (struct in_addr *) CMSG_DATA(cmsg); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
278 *addr = sin->sin_addr; |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
279 |
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
280 #elif (NGX_HAVE_IP_PKTINFO) |
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
281 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
282 cmsg->cmsg_type = IP_PKTINFO; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
283 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
284 len = CMSG_SPACE(sizeof(struct in_pktinfo)); |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
285 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
286 sin = (struct sockaddr_in *) local_sockaddr; |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
287 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
288 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
289 ngx_memzero(pkt, sizeof(struct in_pktinfo)); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
290 pkt->ipi_spec_dst = sin->sin_addr; |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
291 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
292 #endif |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
293 return len; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
294 } |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
295 |
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
296 #endif |
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
297 |
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
298 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
299 if (local_sockaddr->sa_family == AF_INET6) { |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
300 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
301 cmsg->cmsg_level = IPPROTO_IPV6; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
302 cmsg->cmsg_type = IPV6_PKTINFO; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
303 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
304 len = CMSG_SPACE(sizeof(struct in6_pktinfo)); |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
305 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
306 sin6 = (struct sockaddr_in6 *) local_sockaddr; |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
307 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
308 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
309 ngx_memzero(pkt6, sizeof(struct in6_pktinfo)); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
310 pkt6->ipi6_addr = sin6->sin6_addr; |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
311 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
312 return len; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
313 } |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
314 #endif |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
315 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
316 return 0; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
317 } |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
318 |
8003
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
319 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
320 ngx_int_t |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
321 ngx_get_srcaddr_cmsg(struct cmsghdr *cmsg, struct sockaddr *local_sockaddr) |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
322 { |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
323 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
324 #if (NGX_HAVE_IP_RECVDSTADDR) |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
325 struct in_addr *addr; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
326 struct sockaddr_in *sin; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
327 #elif (NGX_HAVE_IP_PKTINFO) |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
328 struct in_pktinfo *pkt; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
329 struct sockaddr_in *sin; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
330 #endif |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
331 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
332 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
333 struct in6_pktinfo *pkt6; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
334 struct sockaddr_in6 *sin6; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
335 #endif |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
336 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
337 |
8116 | 338 #if (NGX_HAVE_IP_RECVDSTADDR) |
8003
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
339 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
340 if (cmsg->cmsg_level == IPPROTO_IP |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
341 && cmsg->cmsg_type == IP_RECVDSTADDR |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
342 && local_sockaddr->sa_family == AF_INET) |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
343 { |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
344 addr = (struct in_addr *) CMSG_DATA(cmsg); |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
345 sin = (struct sockaddr_in *) local_sockaddr; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
346 sin->sin_addr = *addr; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
347 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
348 return NGX_OK; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
349 } |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
350 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
351 #elif (NGX_HAVE_IP_PKTINFO) |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
352 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
353 if (cmsg->cmsg_level == IPPROTO_IP |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
354 && cmsg->cmsg_type == IP_PKTINFO |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
355 && local_sockaddr->sa_family == AF_INET) |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
356 { |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
357 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
358 sin = (struct sockaddr_in *) local_sockaddr; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
359 sin->sin_addr = pkt->ipi_addr; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
360 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
361 return NGX_OK; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
362 } |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
363 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
364 #endif |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
365 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
366 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
367 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
368 if (cmsg->cmsg_level == IPPROTO_IPV6 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
369 && cmsg->cmsg_type == IPV6_PKTINFO |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
370 && local_sockaddr->sa_family == AF_INET6) |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
371 { |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
372 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
373 sin6 = (struct sockaddr_in6 *) local_sockaddr; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
374 sin6->sin6_addr = pkt6->ipi6_addr; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
375 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
376 return NGX_OK; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
377 } |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
378 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
379 #endif |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
380 |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
381 return NGX_DECLINED; |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
382 } |
0f6cc8f73744
Core: added function for local source address cmsg.
Vladimir Homutov <vl@nginx.com>
parents:
8002
diff
changeset
|
383 |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
384 #endif |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
385 |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
386 |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
387 ssize_t |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
388 ngx_sendmsg(ngx_connection_t *c, struct msghdr *msg, int flags) |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
389 { |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
390 ssize_t n; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
391 ngx_err_t err; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
392 #if (NGX_DEBUG) |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
393 size_t size; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
394 ngx_uint_t i; |
6980
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
395 #endif |
dbb0c854e308
Set UDP datagram source address (ticket #1239).
Roman Arutyunyan <arut@nginx.com>
parents:
6692
diff
changeset
|
396 |
6692 | 397 eintr: |
398 | |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
399 n = sendmsg(c->fd, msg, flags); |
6692 | 400 |
401 if (n == -1) { | |
402 err = ngx_errno; | |
403 | |
404 switch (err) { | |
405 case NGX_EAGAIN: | |
406 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
407 "sendmsg() not ready"); | |
408 return NGX_AGAIN; | |
409 | |
410 case NGX_EINTR: | |
411 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
412 "sendmsg() was interrupted"); | |
413 goto eintr; | |
414 | |
415 default: | |
416 c->write->error = 1; | |
417 ngx_connection_error(c, err, "sendmsg() failed"); | |
418 return NGX_ERROR; | |
419 } | |
420 } | |
421 | |
8002
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
422 #if (NGX_DEBUG) |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
423 for (i = 0, size = 0; i < (size_t) msg->msg_iovlen; i++) { |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
424 size += msg->msg_iov[i].iov_len; |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
425 } |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
426 |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
427 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
428 "sendmsg: %z of %uz", n, size); |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
429 #endif |
cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
Vladimir Homutov <vl@nginx.com>
parents:
7665
diff
changeset
|
430 |
6692 | 431 return n; |
432 } |