Skip to content

Commit 149d82e

Browse files
bugfix: wrong source address for the replying packet when received udp packet via req.socket on secondary address. (#233)
1 parent e9cfdc0 commit 149d82e

File tree

4 files changed

+216
-3
lines changed

4 files changed

+216
-3
lines changed

.travis.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ compiler:
1111

1212
addons:
1313
apt:
14-
packages: [ axel, cpanminus, libgd-dev, libtest-base-perl, libtext-diff-perl, liburi-perl, libwww-perl, libtest-longstring-perl, liblist-moreutils-perl ]
14+
packages: [ axel, cpanminus, libgd-dev, libtest-base-perl, libtext-diff-perl, liburi-perl, libwww-perl, libtest-longstring-perl, liblist-moreutils-perl, dnsutils ]
1515

1616
cache:
1717
apt: true
@@ -67,6 +67,8 @@ script:
6767
- sudo iptables -I OUTPUT 1 -p udp --dport 10086 -j REJECT
6868
- sudo iptables -A OUTPUT -p tcp --dst 127.0.0.2 --dport 12345 -j DROP
6969
- sudo iptables -A OUTPUT -p udp --dst 127.0.0.2 --dport 12345 -j DROP
70+
- sudo ip addr add 10.254.254.1/24 dev lo
71+
- sudo ip addr add 10.254.254.2/24 dev lo
7072
- tar zxf download-cache/pcre-$PCRE_VER.tar.gz
7173
- cd pcre-$PCRE_VER/
7274
- ./configure --prefix=$PCRE_PREFIX --enable-jit --enable-utf --enable-unicode-properties > build.log 2>&1 || (cat build.log && exit 1)

src/ngx_stream_lua_socket_udp.c

Lines changed: 151 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ static int ngx_stream_lua_socket_udp_close(lua_State *L);
7171
static ngx_int_t ngx_stream_lua_socket_udp_resume(ngx_stream_lua_request_t *r);
7272
static void ngx_stream_lua_udp_resolve_cleanup(void *data);
7373
static void ngx_stream_lua_udp_socket_cleanup(void *data);
74+
static ssize_t ngx_stream_lua_udp_sendmsg(ngx_connection_t *c,
75+
ngx_iovec_t *vec);
7476

7577

7678
enum {
@@ -786,6 +788,8 @@ ngx_stream_lua_socket_udp_send(lua_State *L)
786788
int type;
787789
const char *msg;
788790
ngx_str_t query;
791+
ngx_iovec_t vec;
792+
struct iovec iovs[1];
789793

790794
ngx_stream_lua_socket_udp_upstream_t *u;
791795
ngx_stream_lua_loc_conf_t *llcf;
@@ -921,9 +925,16 @@ ngx_stream_lua_socket_udp_send(lua_State *L)
921925

922926
dd("sending query %.*s", (int) query.len, query.data);
923927

924-
n = ngx_udp_send(u->udp_connection.connection, query.data, query.len);
928+
vec.iovs = iovs;
929+
vec.nalloc = 1;
930+
vec.count = 1;
931+
iovs[0].iov_base = query.data;
932+
iovs[0].iov_len = query.len;
933+
vec.size = query.len;
934+
n = ngx_stream_lua_udp_sendmsg(u->udp_connection.connection, &vec);
925935

926-
dd("ngx_udp_send returns %d (query len %d)", (int) n, (int) query.len);
936+
dd("ngx_stream_lua_udp_sendmsg returns %d (query len %d)",
937+
(int) n, (int) query.len);
927938

928939
if (n == NGX_ERROR || n == NGX_AGAIN) {
929940
u->socket_errno = ngx_socket_errno;
@@ -1797,4 +1808,142 @@ ngx_stream_lua_req_socket_udp(lua_State *L)
17971808
}
17981809

17991810

1811+
static ssize_t
1812+
ngx_stream_lua_udp_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec)
1813+
{
1814+
ssize_t n;
1815+
ngx_err_t err;
1816+
struct msghdr msg;
1817+
1818+
#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
1819+
1820+
#if (NGX_HAVE_IP_SENDSRCADDR)
1821+
u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))];
1822+
#elif (NGX_HAVE_IP_PKTINFO)
1823+
u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))];
1824+
#endif
1825+
1826+
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
1827+
u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1828+
#endif
1829+
1830+
#endif
1831+
1832+
ngx_memzero(&msg, sizeof(struct msghdr));
1833+
1834+
if (c->socklen) {
1835+
msg.msg_name = c->sockaddr;
1836+
msg.msg_namelen = c->socklen;
1837+
}
1838+
1839+
msg.msg_iov = vec->iovs;
1840+
msg.msg_iovlen = vec->count;
1841+
1842+
#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
1843+
1844+
if (c->listening && c->listening->wildcard && c->local_sockaddr) {
1845+
1846+
#if (NGX_HAVE_IP_SENDSRCADDR)
1847+
1848+
if (c->local_sockaddr->sa_family == AF_INET) {
1849+
struct cmsghdr *cmsg;
1850+
struct in_addr *addr;
1851+
struct sockaddr_in *sin;
1852+
1853+
msg.msg_control = &msg_control;
1854+
msg.msg_controllen = sizeof(msg_control);
1855+
1856+
cmsg = CMSG_FIRSTHDR(&msg);
1857+
cmsg->cmsg_level = IPPROTO_IP;
1858+
cmsg->cmsg_type = IP_SENDSRCADDR;
1859+
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
1860+
1861+
sin = (struct sockaddr_in *) c->local_sockaddr;
1862+
1863+
addr = (struct in_addr *) CMSG_DATA(cmsg);
1864+
*addr = sin->sin_addr;
1865+
}
1866+
1867+
#elif (NGX_HAVE_IP_PKTINFO)
1868+
1869+
if (c->local_sockaddr->sa_family == AF_INET) {
1870+
struct cmsghdr *cmsg;
1871+
struct in_pktinfo *pkt;
1872+
struct sockaddr_in *sin;
1873+
1874+
msg.msg_control = &msg_control;
1875+
msg.msg_controllen = sizeof(msg_control);
1876+
1877+
cmsg = CMSG_FIRSTHDR(&msg);
1878+
cmsg->cmsg_level = IPPROTO_IP;
1879+
cmsg->cmsg_type = IP_PKTINFO;
1880+
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1881+
1882+
sin = (struct sockaddr_in *) c->local_sockaddr;
1883+
1884+
pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
1885+
ngx_memzero(pkt, sizeof(struct in_pktinfo));
1886+
pkt->ipi_spec_dst = sin->sin_addr;
1887+
}
1888+
1889+
#endif
1890+
1891+
#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
1892+
1893+
if (c->local_sockaddr->sa_family == AF_INET6) {
1894+
struct cmsghdr *cmsg;
1895+
struct in6_pktinfo *pkt6;
1896+
struct sockaddr_in6 *sin6;
1897+
1898+
msg.msg_control = &msg_control6;
1899+
msg.msg_controllen = sizeof(msg_control6);
1900+
1901+
cmsg = CMSG_FIRSTHDR(&msg);
1902+
cmsg->cmsg_level = IPPROTO_IPV6;
1903+
cmsg->cmsg_type = IPV6_PKTINFO;
1904+
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1905+
1906+
sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
1907+
1908+
pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
1909+
ngx_memzero(pkt6, sizeof(struct in6_pktinfo));
1910+
pkt6->ipi6_addr = sin6->sin6_addr;
1911+
}
1912+
1913+
#endif
1914+
}
1915+
1916+
#endif
1917+
1918+
eintr:
1919+
1920+
n = sendmsg(c->fd, &msg, 0);
1921+
1922+
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
1923+
"sendto: fd:%d %z of %uz to \"%V\"",
1924+
c->fd, n, vec->size, &c->addr_text);
1925+
if (n == -1) {
1926+
err = ngx_errno;
1927+
1928+
switch (err) {
1929+
case NGX_EAGAIN:
1930+
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
1931+
"sendmsg() not ready");
1932+
return NGX_AGAIN;
1933+
1934+
case NGX_EINTR:
1935+
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
1936+
"sendmsg() was interrupted");
1937+
goto eintr;
1938+
1939+
default:
1940+
c->write->error = 1;
1941+
ngx_connection_error(c, err, "sendmsg() failed");
1942+
return NGX_ERROR;
1943+
}
1944+
}
1945+
1946+
return n;
1947+
}
1948+
18001949
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

t/142-req-udp-socket.t

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,43 @@ hello world! my
243243
received: hello world! my
244244
--- no_error_log
245245
[error]
246+
247+
248+
249+
=== TEST 7: request on secondary ip address
250+
sudo ip addr add 10.254.254.1/24 dev lo
251+
sudo ip addr add 10.254.254.2/24 dev lo
252+
nmap will be blocked by travis , use dig to send dns request.
253+
--- dgram_server_config
254+
content_by_lua_block {
255+
local sock, err = ngx.req.socket()
256+
if not sock then
257+
ngx.log(ngx.ERR,"ngx.req.socket error : ", err)
258+
return ngx.exit(ngx.ERROR)
259+
end
260+
261+
local data = sock:receive()
262+
local ok, err = sock:send(data)
263+
if not ok then
264+
ngx.log(ngx.ERR, "failed to send: ", err)
265+
return ngx.exit(ngx.ERROR)
266+
end
267+
}
268+
--- config
269+
location = /dns {
270+
content_by_lua_block {
271+
local cmd = "dig -b 10.254.254.1 @10.254.254.2 www.baidu.com -p " .. tostring(ngx.var.server_port + 1)
272+
local f = io.popen(cmd, "r")
273+
ngx.sleep(0.2)
274+
local result = f:read("*a")
275+
f:close()
276+
ngx.say("hello")
277+
}
278+
}
279+
--- request
280+
GET /dns
281+
--- response_body
282+
hello
283+
--- grep_error_log eval: qr/sendto: fd.*$/
284+
--- grep_error_log_out eval
285+
qr/sendto: fd:\d+ \d+ of \d+ to "10.254.254.1"/

valgrind.suppress

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,25 @@
196196
fun:ngx_set_environment
197197
fun:ngx_single_process_cycle
198198
}
199+
{
200+
<insert_a_suppression_name_here>
201+
Memcheck:Param
202+
sendmsg(msg.msg_control)
203+
fun:sendmsg
204+
fun:ngx_stream_lua_udp_sendmsg
205+
fun:ngx_stream_lua_socket_udp_send
206+
fun:lj_BC_FUNCC
207+
fun:ngx_stream_lua_run_thread
208+
fun:ngx_stream_lua_content_by_chunk
209+
fun:ngx_stream_lua_content_handler_inline
210+
fun:ngx_stream_lua_content_handler
211+
fun:ngx_stream_core_content_phase
212+
fun:ngx_stream_core_run_phases
213+
fun:ngx_stream_session_handler
214+
fun:ngx_stream_init_connection
215+
fun:ngx_event_recvmsg
216+
fun:ngx_epoll_process_events
217+
fun:ngx_process_events_and_timers
218+
fun:ngx_single_process_cycle
219+
fun:main
220+
}

0 commit comments

Comments
 (0)