Changeset 6980:dbb0c854e308 in nginx


Ignore:
Timestamp:
04/11/17 13:41:53 (4 months ago)
Author:
Roman Arutyunyan <arut@…>
Branch:
default
Message:

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.

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • auto/unix

    r6724 r6980  
    392392ngx_feature_libs=
    393393ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_RECVDSTADDR, NULL, 0)"
     394. auto/feature
     395
     396
     397# BSD way to set IPv4 datagram source address
     398
     399ngx_feature="IP_SENDSRCADDR"
     400ngx_feature_name="NGX_HAVE_IP_SENDSRCADDR"
     401ngx_feature_run=no
     402ngx_feature_incs="#include <sys/socket.h>
     403                  #include <netinet/in.h>"
     404ngx_feature_path=
     405ngx_feature_libs=
     406ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_SENDSRCADDR, NULL, 0)"
    394407. auto/feature
    395408
  • src/os/unix/ngx_udp_sendmsg_chain.c

    r6692 r6980  
    204204    struct msghdr  msg;
    205205
     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
    206220    ngx_memzero(&msg, sizeof(struct msghdr));
    207221
     
    213227    msg.msg_iov = vec->iovs;
    214228    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
    215305
    216306eintr:
Note: See TracChangeset for help on using the changeset viewer.