mirror of
https://github.com/nginx/nginx.git
synced 2024-11-24 13:49:05 +08:00
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.
This commit is contained in:
parent
62b20ce87a
commit
05841adfb2
13
auto/unix
13
auto/unix
@ -394,6 +394,19 @@ ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_RECVDSTADDR, NULL, 0)"
|
||||
. auto/feature
|
||||
|
||||
|
||||
# BSD way to set IPv4 datagram source address
|
||||
|
||||
ngx_feature="IP_SENDSRCADDR"
|
||||
ngx_feature_name="NGX_HAVE_IP_SENDSRCADDR"
|
||||
ngx_feature_run=no
|
||||
ngx_feature_incs="#include <sys/socket.h>
|
||||
#include <netinet/in.h>"
|
||||
ngx_feature_path=
|
||||
ngx_feature_libs=
|
||||
ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_SENDSRCADDR, NULL, 0)"
|
||||
. auto/feature
|
||||
|
||||
|
||||
# Linux way to get IPv4 datagram destination address
|
||||
|
||||
ngx_feature="IP_PKTINFO"
|
||||
|
@ -203,6 +203,20 @@ ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec)
|
||||
ngx_err_t err;
|
||||
struct msghdr msg;
|
||||
|
||||
#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
|
||||
|
||||
#if (NGX_HAVE_IP_SENDSRCADDR)
|
||||
u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))];
|
||||
#elif (NGX_HAVE_IP_PKTINFO)
|
||||
u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
ngx_memzero(&msg, sizeof(struct msghdr));
|
||||
|
||||
if (c->socklen) {
|
||||
@ -213,6 +227,82 @@ ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec)
|
||||
msg.msg_iov = vec->iovs;
|
||||
msg.msg_iovlen = vec->count;
|
||||
|
||||
#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
|
||||
|
||||
if (c->listening && c->listening->wildcard && c->local_sockaddr) {
|
||||
|
||||
#if (NGX_HAVE_IP_SENDSRCADDR)
|
||||
|
||||
if (c->local_sockaddr->sa_family == AF_INET) {
|
||||
struct cmsghdr *cmsg;
|
||||
struct in_addr *addr;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = IPPROTO_IP;
|
||||
cmsg->cmsg_type = IP_SENDSRCADDR;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
|
||||
|
||||
sin = (struct sockaddr_in *) c->local_sockaddr;
|
||||
|
||||
addr = (struct in_addr *) CMSG_DATA(cmsg);
|
||||
*addr = sin->sin_addr;
|
||||
}
|
||||
|
||||
#elif (NGX_HAVE_IP_PKTINFO)
|
||||
|
||||
if (c->local_sockaddr->sa_family == AF_INET) {
|
||||
struct cmsghdr *cmsg;
|
||||
struct in_pktinfo *pkt;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = IPPROTO_IP;
|
||||
cmsg->cmsg_type = IP_PKTINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
||||
|
||||
sin = (struct sockaddr_in *) c->local_sockaddr;
|
||||
|
||||
pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
|
||||
ngx_memzero(pkt, sizeof(struct in_pktinfo));
|
||||
pkt->ipi_spec_dst = sin->sin_addr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
|
||||
|
||||
if (c->local_sockaddr->sa_family == AF_INET6) {
|
||||
struct cmsghdr *cmsg;
|
||||
struct in6_pktinfo *pkt6;
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
msg.msg_control = &msg_control6;
|
||||
msg.msg_controllen = sizeof(msg_control6);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||
cmsg->cmsg_type = IPV6_PKTINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||
|
||||
sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
|
||||
|
||||
pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
|
||||
ngx_memzero(pkt6, sizeof(struct in6_pktinfo));
|
||||
pkt6->ipi6_addr = sin6->sin6_addr;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
eintr:
|
||||
|
||||
n = sendmsg(c->fd, &msg, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user