Mercurial > hg > nginx
comparison src/os/unix/ngx_udp_sendmsg_chain.c @ 6980:dbb0c854e308
Set UDP datagram source address (ticket #1239).
Previously, the source IP address of a response UDP datagram could differ from
the original datagram destination address. This could happen if the server UDP
socket is bound to a wildcard address and the network interface chosen to output
the response packet has a different default address than the destination address
of the original packet. For example, if two addresses from the same network are
configured on an interface.
Now source address is set explicitly if a response is sent for a server UDP
socket bound to a wildcard address.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Tue, 11 Apr 2017 16:41:53 +0300 |
parents | 56fc55e32f23 |
children | 8ce1a34f160b |
comparison
equal
deleted
inserted
replaced
6979:ef935cd7ed8d | 6980:dbb0c854e308 |
---|---|
201 { | 201 { |
202 ssize_t n; | 202 ssize_t n; |
203 ngx_err_t err; | 203 ngx_err_t err; |
204 struct msghdr msg; | 204 struct msghdr msg; |
205 | 205 |
206 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | |
207 | |
208 #if (NGX_HAVE_IP_SENDSRCADDR) | |
209 u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))]; | |
210 #elif (NGX_HAVE_IP_PKTINFO) | |
211 u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))]; | |
212 #endif | |
213 | |
214 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | |
215 u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; | |
216 #endif | |
217 | |
218 #endif | |
219 | |
206 ngx_memzero(&msg, sizeof(struct msghdr)); | 220 ngx_memzero(&msg, sizeof(struct msghdr)); |
207 | 221 |
208 if (c->socklen) { | 222 if (c->socklen) { |
209 msg.msg_name = c->sockaddr; | 223 msg.msg_name = c->sockaddr; |
210 msg.msg_namelen = c->socklen; | 224 msg.msg_namelen = c->socklen; |
211 } | 225 } |
212 | 226 |
213 msg.msg_iov = vec->iovs; | 227 msg.msg_iov = vec->iovs; |
214 msg.msg_iovlen = vec->count; | 228 msg.msg_iovlen = vec->count; |
229 | |
230 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | |
231 | |
232 if (c->listening && c->listening->wildcard && c->local_sockaddr) { | |
233 | |
234 #if (NGX_HAVE_IP_SENDSRCADDR) | |
235 | |
236 if (c->local_sockaddr->sa_family == AF_INET) { | |
237 struct cmsghdr *cmsg; | |
238 struct in_addr *addr; | |
239 struct sockaddr_in *sin; | |
240 | |
241 msg.msg_control = &msg_control; | |
242 msg.msg_controllen = sizeof(msg_control); | |
243 | |
244 cmsg = CMSG_FIRSTHDR(&msg); | |
245 cmsg->cmsg_level = IPPROTO_IP; | |
246 cmsg->cmsg_type = IP_SENDSRCADDR; | |
247 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); | |
248 | |
249 sin = (struct sockaddr_in *) c->local_sockaddr; | |
250 | |
251 addr = (struct in_addr *) CMSG_DATA(cmsg); | |
252 *addr = sin->sin_addr; | |
253 } | |
254 | |
255 #elif (NGX_HAVE_IP_PKTINFO) | |
256 | |
257 if (c->local_sockaddr->sa_family == AF_INET) { | |
258 struct cmsghdr *cmsg; | |
259 struct in_pktinfo *pkt; | |
260 struct sockaddr_in *sin; | |
261 | |
262 msg.msg_control = &msg_control; | |
263 msg.msg_controllen = sizeof(msg_control); | |
264 | |
265 cmsg = CMSG_FIRSTHDR(&msg); | |
266 cmsg->cmsg_level = IPPROTO_IP; | |
267 cmsg->cmsg_type = IP_PKTINFO; | |
268 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); | |
269 | |
270 sin = (struct sockaddr_in *) c->local_sockaddr; | |
271 | |
272 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); | |
273 ngx_memzero(pkt, sizeof(struct in_pktinfo)); | |
274 pkt->ipi_spec_dst = sin->sin_addr; | |
275 } | |
276 | |
277 #endif | |
278 | |
279 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | |
280 | |
281 if (c->local_sockaddr->sa_family == AF_INET6) { | |
282 struct cmsghdr *cmsg; | |
283 struct in6_pktinfo *pkt6; | |
284 struct sockaddr_in6 *sin6; | |
285 | |
286 msg.msg_control = &msg_control6; | |
287 msg.msg_controllen = sizeof(msg_control6); | |
288 | |
289 cmsg = CMSG_FIRSTHDR(&msg); | |
290 cmsg->cmsg_level = IPPROTO_IPV6; | |
291 cmsg->cmsg_type = IPV6_PKTINFO; | |
292 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); | |
293 | |
294 sin6 = (struct sockaddr_in6 *) c->local_sockaddr; | |
295 | |
296 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); | |
297 ngx_memzero(pkt6, sizeof(struct in6_pktinfo)); | |
298 pkt6->ipi6_addr = sin6->sin6_addr; | |
299 } | |
300 | |
301 #endif | |
302 } | |
303 | |
304 #endif | |
215 | 305 |
216 eintr: | 306 eintr: |
217 | 307 |
218 n = sendmsg(c->fd, &msg, 0); | 308 n = sendmsg(c->fd, &msg, 0); |
219 | 309 |