comparison src/os/unix/ngx_udp_sendmsg_chain.c @ 8002:cfe1284e5d1d

Core: made the ngx_sendmsg() function non-static. The NGX_HAVE_ADDRINFO_CMSG macro is defined when at least one of methods to deal with corresponding control message is available.
author Vladimir Homutov <vl@nginx.com>
date Tue, 25 Jan 2022 15:48:56 +0300
parents d127837c714f
children 0f6cc8f73744
comparison
equal deleted inserted replaced
8001:8206ecdcd837 8002:cfe1284e5d1d
10 #include <ngx_event.h> 10 #include <ngx_event.h>
11 11
12 12
13 static ngx_chain_t *ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec, 13 static ngx_chain_t *ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec,
14 ngx_chain_t *in, ngx_log_t *log); 14 ngx_chain_t *in, ngx_log_t *log);
15 static ssize_t ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec); 15 static ssize_t ngx_sendmsg_vec(ngx_connection_t *c, ngx_iovec_t *vec);
16 16
17 17
18 ngx_chain_t * 18 ngx_chain_t *
19 ngx_udp_unix_sendmsg_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) 19 ngx_udp_unix_sendmsg_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
20 { 20 {
86 return in; 86 return in;
87 } 87 }
88 88
89 send += vec.size; 89 send += vec.size;
90 90
91 n = ngx_sendmsg(c, &vec); 91 n = ngx_sendmsg_vec(c, &vec);
92 92
93 if (n == NGX_ERROR) { 93 if (n == NGX_ERROR) {
94 return NGX_CHAIN_ERROR; 94 return NGX_CHAIN_ERROR;
95 } 95 }
96 96
202 return in; 202 return in;
203 } 203 }
204 204
205 205
206 static ssize_t 206 static ssize_t
207 ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec) 207 ngx_sendmsg_vec(ngx_connection_t *c, ngx_iovec_t *vec)
208 { 208 {
209 ssize_t n; 209 struct msghdr msg;
210 ngx_err_t err; 210
211 struct msghdr msg; 211 #if (NGX_HAVE_ADDRINFO_CMSG)
212 212 struct cmsghdr *cmsg;
213 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) 213 u_char msg_control[CMSG_SPACE(sizeof(ngx_addrinfo_t))];
214
215 #if (NGX_HAVE_IP_SENDSRCADDR)
216 u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))];
217 #elif (NGX_HAVE_IP_PKTINFO)
218 u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))];
219 #endif
220
221 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
222 u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
223 #endif
224
225 #endif 214 #endif
226 215
227 ngx_memzero(&msg, sizeof(struct msghdr)); 216 ngx_memzero(&msg, sizeof(struct msghdr));
228 217
229 if (c->socklen) { 218 if (c->socklen) {
232 } 221 }
233 222
234 msg.msg_iov = vec->iovs; 223 msg.msg_iov = vec->iovs;
235 msg.msg_iovlen = vec->count; 224 msg.msg_iovlen = vec->count;
236 225
237 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) 226 #if (NGX_HAVE_ADDRINFO_CMSG)
238
239 if (c->listening && c->listening->wildcard && c->local_sockaddr) { 227 if (c->listening && c->listening->wildcard && c->local_sockaddr) {
240 228
229 msg.msg_control = msg_control;
230 msg.msg_controllen = sizeof(msg_control);
231 ngx_memzero(msg_control, sizeof(msg_control));
232
233 cmsg = CMSG_FIRSTHDR(&msg);
234
235 msg.msg_controllen = ngx_set_srcaddr_cmsg(cmsg, c->local_sockaddr);
236 }
237 #endif
238
239 return ngx_sendmsg(c, &msg, 0);
240 }
241
242
243 #if (NGX_HAVE_ADDRINFO_CMSG)
244
245 size_t
246 ngx_set_srcaddr_cmsg(struct cmsghdr *cmsg, struct sockaddr *local_sockaddr)
247 {
248 size_t len;
241 #if (NGX_HAVE_IP_SENDSRCADDR) 249 #if (NGX_HAVE_IP_SENDSRCADDR)
242 250 struct in_addr *addr;
243 if (c->local_sockaddr->sa_family == AF_INET) { 251 struct sockaddr_in *sin;
244 struct cmsghdr *cmsg;
245 struct in_addr *addr;
246 struct sockaddr_in *sin;
247
248 msg.msg_control = &msg_control;
249 msg.msg_controllen = sizeof(msg_control);
250
251 cmsg = CMSG_FIRSTHDR(&msg);
252 cmsg->cmsg_level = IPPROTO_IP;
253 cmsg->cmsg_type = IP_SENDSRCADDR;
254 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
255
256 sin = (struct sockaddr_in *) c->local_sockaddr;
257
258 addr = (struct in_addr *) CMSG_DATA(cmsg);
259 *addr = sin->sin_addr;
260 }
261
262 #elif (NGX_HAVE_IP_PKTINFO) 252 #elif (NGX_HAVE_IP_PKTINFO)
263 253 struct in_pktinfo *pkt;
264 if (c->local_sockaddr->sa_family == AF_INET) { 254 struct sockaddr_in *sin;
265 struct cmsghdr *cmsg;
266 struct in_pktinfo *pkt;
267 struct sockaddr_in *sin;
268
269 msg.msg_control = &msg_control;
270 msg.msg_controllen = sizeof(msg_control);
271
272 cmsg = CMSG_FIRSTHDR(&msg);
273 cmsg->cmsg_level = IPPROTO_IP;
274 cmsg->cmsg_type = IP_PKTINFO;
275 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
276
277 sin = (struct sockaddr_in *) c->local_sockaddr;
278
279 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
280 ngx_memzero(pkt, sizeof(struct in_pktinfo));
281 pkt->ipi_spec_dst = sin->sin_addr;
282 }
283
284 #endif 255 #endif
285 256
286 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) 257 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
287 258 struct in6_pktinfo *pkt6;
288 if (c->local_sockaddr->sa_family == AF_INET6) { 259 struct sockaddr_in6 *sin6;
289 struct cmsghdr *cmsg; 260 #endif
290 struct in6_pktinfo *pkt6; 261
291 struct sockaddr_in6 *sin6; 262
292 263 #if (NGX_HAVE_IP_SENDSRCADDR) || (NGX_HAVE_IP_PKTINFO)
293 msg.msg_control = &msg_control6; 264
294 msg.msg_controllen = sizeof(msg_control6); 265 if (local_sockaddr->sa_family == AF_INET) {
295 266
296 cmsg = CMSG_FIRSTHDR(&msg); 267 cmsg->cmsg_level = IPPROTO_IP;
297 cmsg->cmsg_level = IPPROTO_IPV6; 268
298 cmsg->cmsg_type = IPV6_PKTINFO; 269 #if (NGX_HAVE_IP_SENDSRCADDR)
299 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 270
300 271 cmsg->cmsg_type = IP_SENDSRCADDR;
301 sin6 = (struct sockaddr_in6 *) c->local_sockaddr; 272 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
302 273 len = CMSG_SPACE(sizeof(struct in_addr));
303 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); 274
304 ngx_memzero(pkt6, sizeof(struct in6_pktinfo)); 275 sin = (struct sockaddr_in *) local_sockaddr;
305 pkt6->ipi6_addr = sin6->sin6_addr; 276
306 } 277 addr = (struct in_addr *) CMSG_DATA(cmsg);
307 278 *addr = sin->sin_addr;
308 #endif 279
309 } 280 #elif (NGX_HAVE_IP_PKTINFO)
310 281
282 cmsg->cmsg_type = IP_PKTINFO;
283 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
284 len = CMSG_SPACE(sizeof(struct in_pktinfo));
285
286 sin = (struct sockaddr_in *) local_sockaddr;
287
288 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
289 ngx_memzero(pkt, sizeof(struct in_pktinfo));
290 pkt->ipi_spec_dst = sin->sin_addr;
291
292 #endif
293 return len;
294 }
295
296 #endif
297
298 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
299 if (local_sockaddr->sa_family == AF_INET6) {
300
301 cmsg->cmsg_level = IPPROTO_IPV6;
302 cmsg->cmsg_type = IPV6_PKTINFO;
303 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
304 len = CMSG_SPACE(sizeof(struct in6_pktinfo));
305
306 sin6 = (struct sockaddr_in6 *) local_sockaddr;
307
308 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
309 ngx_memzero(pkt6, sizeof(struct in6_pktinfo));
310 pkt6->ipi6_addr = sin6->sin6_addr;
311
312 return len;
313 }
314 #endif
315
316 return 0;
317 }
318
319 #endif
320
321
322 ssize_t
323 ngx_sendmsg(ngx_connection_t *c, struct msghdr *msg, int flags)
324 {
325 ssize_t n;
326 ngx_err_t err;
327 #if (NGX_DEBUG)
328 size_t size;
329 ngx_uint_t i;
311 #endif 330 #endif
312 331
313 eintr: 332 eintr:
314 333
315 n = sendmsg(c->fd, &msg, 0); 334 n = sendmsg(c->fd, msg, flags);
316
317 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
318 "sendmsg: %z of %uz", n, vec->size);
319 335
320 if (n == -1) { 336 if (n == -1) {
321 err = ngx_errno; 337 err = ngx_errno;
322 338
323 switch (err) { 339 switch (err) {
336 ngx_connection_error(c, err, "sendmsg() failed"); 352 ngx_connection_error(c, err, "sendmsg() failed");
337 return NGX_ERROR; 353 return NGX_ERROR;
338 } 354 }
339 } 355 }
340 356
357 #if (NGX_DEBUG)
358 for (i = 0, size = 0; i < (size_t) msg->msg_iovlen; i++) {
359 size += msg->msg_iov[i].iov_len;
360 }
361
362 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
363 "sendmsg: %z of %uz", n, size);
364 #endif
365
341 return n; 366 return n;
342 } 367 }