Merge 0.9->trunk
authorMatthew Wild <mwild1@gmail.com>
Tue, 18 Jun 2013 11:17:06 +0000 (12:17 +0100)
committerMatthew Wild <mwild1@gmail.com>
Tue, 18 Jun 2013 11:17:06 +0000 (12:17 +0100)
plugins/mod_s2s/s2sout.lib.lua
util-src/Makefile
util-src/net.c [new file with mode: 0644]

index cb2f8be4f8e791cc7c10ba3dbcd0ce04c885dc22..575d37acc676369bcdd7b1eb1f68ea46f2a2d4cb 100644 (file)
@@ -18,7 +18,7 @@ local socket = require "socket";
 local adns = require "net.adns";
 local dns = require "net.dns";
 local t_insert, t_sort, ipairs = table.insert, table.sort, ipairs;
-local st = require "util.stanza";
+local local_addresses = require "util.net".local_addresses;
 
 local s2s_destroy_session = require "core.s2smanager".destroy_session;
 
@@ -47,7 +47,6 @@ end
 function s2sout.initiate_connection(host_session)
        initialize_filters(host_session);
        host_session.version = 1;
-       host_session.open_stream = session_open_stream;
        
        -- Kick the connection attempting machine into life
        if not s2sout.attempt_connection(host_session) then
@@ -74,7 +73,7 @@ function s2sout.initiate_connection(host_session)
 end
 
 function s2sout.attempt_connection(host_session, err)
-       local from_host, to_host = host_session.from_host, host_session.to_host;
+       local to_host = host_session.to_host;
        local connect_host, connect_port = to_host and idna_to_ascii(to_host), 5269;
        
        if not connect_host then
@@ -267,19 +266,19 @@ end
 
 function s2sout.make_connect(host_session, connect_host, connect_port)
        (host_session.log or log)("info", "Beginning new connection attempt to %s ([%s]:%d)", host_session.to_host, connect_host.addr, connect_port);
-       -- Ok, we're going to try to connect
-       
-       local from_host, to_host = host_session.from_host, host_session.to_host;
-       
+
        -- Reset secure flag in case this is another
        -- connection attempt after a failed STARTTLS
        host_session.secure = nil;
 
        local conn, handler;
-       if connect_host.proto == "IPv4" then
+       local proto = connect_host.proto;
+       if proto == "IPv4" then
                conn, handler = socket.tcp();
-       else
+       elseif proto == "IPv6" and socket.tcp6 then
                conn, handler = socket.tcp6();
+       else
+               handler = "Unsupported protocol: "..tostring(proto);
        end
        
        if not conn then
@@ -330,20 +329,12 @@ module:hook_global("service-added", function (event)
        end
        for source, _ in pairs(s2s_sources) do
                if source == "*" or source == "0.0.0.0" then
-                       if not socket.local_addresses then
-                               sources[#sources + 1] = new_ip("0.0.0.0", "IPv4");
-                       else
-                               for _, addr in ipairs(socket.local_addresses("ipv4", true)) do
-                                       sources[#sources + 1] = new_ip(addr, "IPv4");
-                               end
+                       for _, addr in ipairs(local_addresses("ipv4", true)) do
+                               sources[#sources + 1] = new_ip(addr, "IPv4");
                        end
                elseif source == "::" then
-                       if not socket.local_addresses then
-                               sources[#sources + 1] = new_ip("::", "IPv6");
-                       else
-                               for _, addr in ipairs(socket.local_addresses("ipv6", true)) do
-                                       sources[#sources + 1] = new_ip(addr, "IPv6");
-                               end
+                       for _, addr in ipairs(local_addresses("ipv6", true)) do
+                               sources[#sources + 1] = new_ip(addr, "IPv6");
                        end
                else
                        sources[#sources + 1] = new_ip(source, (source:find(":") and "IPv6") or "IPv4");
index 90d65e514d8eb68e6307aa1ecafaaf7fda298e42..3a1ba3f2af1f69f506c6ddfb93c5c4f51837e90c 100644 (file)
@@ -14,9 +14,9 @@ CFLAGS+=-ggdb
 .PHONY: all install clean
 .SUFFIXES: .c .o .so
 
-all: encodings.so hashes.so pposix.so signal.so
+all: encodings.so hashes.so net.so pposix.so signal.so
 
-install: encodings.so hashes.so pposix.so signal.so
+install: encodings.so hashes.so net.so pposix.so signal.so
        install *.so ../util/
 
 clean:
diff --git a/util-src/net.c b/util-src/net.c
new file mode 100644 (file)
index 0000000..497cd95
--- /dev/null
@@ -0,0 +1,107 @@
+/* Prosody IM
+--
+-- This project is MIT/X11 licensed. Please see the
+-- COPYING file in the source package for more information.
+--
+-- Copyright (C) 2012 Paul Aurich
+-- Copyright (C) 2013 Matthew Wild
+-- Copyright (C) 2013 Florian Zeitz
+--
+*/
+
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef _WIN32
+  #include <sys/ioctl.h>
+  #include <sys/types.h>
+  #include <sys/socket.h>
+  #include <net/if.h>
+  #include <ifaddrs.h>
+  #include <arpa/inet.h>
+#endif
+
+#include <lua.h>
+#include <lauxlib.h>
+
+/* Enumerate all locally configured IP addresses */
+
+const char * const type_strings[] = {
+       "both",
+       "ipv4",
+       "ipv6",
+       NULL
+};
+
+static int lc_local_addresses(lua_State *L)
+{
+       /* Link-local IPv4 addresses; see RFC 3927 and RFC 5735 */
+       const long ip4_linklocal = htonl(0xa9fe0000); /* 169.254.0.0 */
+       const long ip4_mask      = htonl(0xffff0000);
+#ifndef _WIN32
+       struct ifaddrs *addr = NULL, *a;
+       int n = 1;
+#endif
+       int type = luaL_checkoption(L, 1, "both", type_strings);
+       const char link_local = lua_toboolean(L, 2); /* defaults to 0 (false) */
+       const char ipv4 = (type == 0 || type == 1);
+       const char ipv6 = (type == 0 || type == 2);
+
+#ifndef _WIN32
+       if (getifaddrs(&addr) < 0) {
+               lua_pushnil(L);
+               lua_pushfstring(L, "getifaddrs failed (%d): %s", errno,
+               strerror(errno));
+               return 2;
+       }
+
+       lua_newtable(L);
+
+       for (a = addr; a; a = a->ifa_next) {
+               int family;
+               char ipaddr[INET6_ADDRSTRLEN];
+               const char *tmp = NULL;
+
+               if (a->ifa_addr == NULL || a->ifa_flags & IFF_LOOPBACK)
+                       continue;
+
+               family = a->ifa_addr->sa_family;
+
+               if (ipv4 && family == AF_INET) {
+                       struct sockaddr_in *sa = (struct sockaddr_in *)a->ifa_addr;
+                       if (!link_local &&((sa->sin_addr.s_addr & ip4_mask) == ip4_linklocal))
+                               continue;
+                       tmp = inet_ntop(family, &sa->sin_addr, ipaddr, sizeof(ipaddr));
+               } else if (ipv6 && family == AF_INET6) {
+                       struct sockaddr_in6 *sa = (struct sockaddr_in6 *)a->ifa_addr;
+                       if (!link_local && IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr))
+                               continue;
+                       if (IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&sa->sin6_addr))
+                               continue;
+                       tmp = inet_ntop(family, &sa->sin6_addr, ipaddr, sizeof(ipaddr));
+               }
+
+               if (tmp != NULL) {
+                       lua_pushstring(L, tmp);
+                       lua_rawseti(L, -2, n++);
+               }
+               /* TODO: Error reporting? */
+       }
+
+       freeifaddrs(addr);
+
+       return 1;
+#endif
+}
+
+int luaopen_util_net(lua_State* L)
+{
+       luaL_Reg exports[] = {
+               { "local_addresses", lc_local_addresses },
+               { NULL, NULL }
+       };
+
+       luaL_register(L, "net",  exports);
+       return 1;
+}