Welcome! Log In Create A New Profile

Advanced

[nginx] Set UDP datagram source address (ticket #1239).

Roman Arutyunyan
April 18, 2017 08:04AM
details: http://hg.nginx.org/nginx/rev/dbb0c854e308
branches:
changeset: 6980:dbb0c854e308
user: Roman Arutyunyan <arut@nginx.com>
date: Tue Apr 11 16:41:53 2017 +0300
description:
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.

diffstat:

auto/unix | 13 +++++
src/os/unix/ngx_udp_sendmsg_chain.c | 90 +++++++++++++++++++++++++++++++++++++
2 files changed, 103 insertions(+), 0 deletions(-)

diffs (130 lines):

diff -r ef935cd7ed8d -r dbb0c854e308 auto/unix
--- a/auto/unix Tue Apr 18 13:01:19 2017 +0300
+++ b/auto/unix Tue Apr 11 16:41:53 2017 +0300
@@ -394,6 +394,19 @@ ngx_feature_test="setsockopt(0, IPPROTO_
. 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"
diff -r ef935cd7ed8d -r dbb0c854e308 src/os/unix/ngx_udp_sendmsg_chain.c
--- a/src/os/unix/ngx_udp_sendmsg_chain.c Tue Apr 18 13:01:19 2017 +0300
+++ b/src/os/unix/ngx_udp_sendmsg_chain.c Tue Apr 11 16:41:53 2017 +0300
@@ -203,6 +203,20 @@ ngx_sendmsg(ngx_connection_t *c, ngx_iov
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_iov
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);
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[nginx] Set UDP datagram source address (ticket #1239).

Roman Arutyunyan 522 April 18, 2017 08:04AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 298
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready