From 6edab865f661edf732d30232808118585cc2a1c7 Mon Sep 17 00:00:00 2001 From: Tim Duesterhus Date: Sat, 6 Jan 2018 19:04:45 +0100 Subject: [PATCH] BUG/MEDIUM: lua: Fix IPv6 with separate port support for Socket.connect The `socket.tcp.connect` method of Lua requires at least two parameters: The host and the port. The `Socket.connect` method of haproxy requires only one when a host with a combined port is provided. This stems from the fact that `str2sa_range` is used internally in `hlua_socket_connect`. This very fact unfortunately causes a diversion in the behaviour of Lua's socket class and haproxy's for IPv6 addresses: sock:connect("::1", "80") works fine with Lua, but fails with: connect: cannot parse destination address '::1' in haproxy, because `str2sa_range` parses the trailing `:1` as the port. This patch forcefully adds a `:` to the end of the address iff a port number greater than `0` is given as the second parameter. Technically this breaks backwards compatibility, because the docs state: > The syntax "127.0.0.1:1234" is valid. in this case, the > parameter *port* is ignored. But: The connect() call can only succeed if the second parameter is left out (which causes no breakage) or if the second parameter is an integer or a numeric string. It seems unlikely that someone would provide an address with a port number and would also provide a second parameter containing a number other than zero. Thus I feel this breakage is warranted to fix the mismatch between haproxy's socket class and Lua's one. This commit should be backported to haproxy 1.8 only, because of the possible breakage of existing Lua scripts. --- doc/lua-api/index.rst | 2 +- src/hlua.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst index dceab01d7..7fe609fc9 100644 --- a/doc/lua-api/index.rst +++ b/doc/lua-api/index.rst @@ -1769,7 +1769,7 @@ Socket class "abns@", and finaly a filedescriotr can be passed with the prefix "fd@". The prefix "ipv4@", "ipv6@" and "unix@" are also supported. The port can be passed int the string. The syntax "127.0.0.1:1234" is valid. in this case, the - parameter *port* is ignored. + parameter *port* must not be set. .. js:function:: Socket.connect_ssl(socket, address, port) diff --git a/src/hlua.c b/src/hlua.c index 3b4fc3b54..3d5a81cac 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -2333,9 +2333,22 @@ __LJMP static int hlua_socket_connect(struct lua_State *L) WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread")); ip = MAY_LJMP(luaL_checkstring(L, 2)); - if (lua_gettop(L) >= 3) + if (lua_gettop(L) >= 3) { + luaL_Buffer b; port = MAY_LJMP(luaL_checkinteger(L, 3)); + /* Force the ip to end with a colon, to support IPv6 addresses + * that are not enclosed within square brackets. + */ + if (port > 0) { + luaL_buffinit(L, &b); + luaL_addstring(&b, ip); + luaL_addchar(&b, ':'); + luaL_pushresult(&b); + ip = lua_tolstring(L, lua_gettop(L), NULL); + } + } + /* check for connection break. If some data where read, return it. */ peer = xref_get_peer_and_lock(&socket->xref); if (!peer) {