diff --git a/CHANGELOG b/CHANGELOG
index a9ff7bc16..e5ebedcf1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,9 @@
# Nmap Changelog ($Id$); -*-text-*-
+o [NSE] Added nmap.get_interface and nmap.get_interface_info functions
+ so scripts can access characteristics of the scanning interface.
+ [Djalal]
+
o [NSE] Added epmd-info.nse, which gets a list of Erlang node port
numbers. [Toni Ruottu]
diff --git a/nse_dnet.cc b/nse_dnet.cc
index 7b6b69fec..1015436a6 100644
--- a/nse_dnet.cc
+++ b/nse_dnet.cc
@@ -47,6 +47,72 @@ LUALIB_API int l_dnet_new (lua_State *L)
return 1;
}
+LUALIB_API int l_dnet_get_interface_info (lua_State *L)
+{
+ char ipstr[INET6_ADDRSTRLEN];
+ struct addr src, bcast;
+ struct interface_info *ii = getInterfaceByName(luaL_checkstring(L, 1));
+
+ if (ii == NULL) {
+ lua_pushnil(L);
+ lua_pushstring(L, "failed to find interface");
+ return 2;
+ }
+
+ memset(ipstr, 0, INET6_ADDRSTRLEN);
+ memset(&src, 0, sizeof(src));
+ memset(&bcast, 0, sizeof(bcast));
+ lua_newtable(L);
+
+ setsfield(L, -1, "device", ii->devfullname);
+ setsfield(L, -1, "shortname", ii->devname);
+ setnfield(L, -1, "netmask", ii->netmask_bits);
+
+ if (ii->addr.ss_family == AF_INET)
+ inet_ntop(AF_INET, &((struct sockaddr_in *)&ii->addr)->sin_addr,
+ ipstr, INET6_ADDRSTRLEN);
+ else if (ii->addr.ss_family == AF_INET6)
+ inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&ii->addr)->sin6_addr,
+ ipstr, INET6_ADDRSTRLEN);
+ else
+ luaL_error(L, "unknown protocol");
+
+ setsfield(L, -1, "address", ipstr);
+
+ switch (ii->device_type) {
+ case devt_ethernet:
+ setsfield(L, -1, "link", "ethernet");
+ lua_pushlstring(L, (const char *) ii->mac, 6);
+ lua_setfield(L, -2, "mac");
+
+ /* calculate the broadcast address */
+ if (ii->addr.ss_family == AF_INET) {
+ src.addr_type = ADDR_TYPE_IP;
+ src.addr_bits = ii->netmask_bits;
+ src.addr_ip = ((struct sockaddr_in *)&ii->addr)->sin_addr.s_addr;
+ addr_bcast(&src, &bcast);
+ memset(ipstr, 0, INET6_ADDRSTRLEN);
+ if (addr_ntop(&bcast, ipstr, INET6_ADDRSTRLEN) != NULL)
+ setsfield(L, -1, "broadcast", ipstr);
+ }
+ break;
+ case devt_loopback:
+ setsfield(L, -1, "link", "loopback");
+ break;
+ case devt_p2p:
+ setsfield(L, -1, "link", "p2p");
+ break;
+ case devt_other:
+ default:
+ setsfield(L, -1, "link", "other");
+ }
+
+ setsfield(L, -1, "up", (ii->device_up ? "up" : "down"));
+ setnfield(L, -1, "mtu", ii->mtu);
+
+ return 1;
+}
+
LUALIB_API int l_dnet_get_interface_link (lua_State *L)
{
struct interface_info *ii = getInterfaceByName(luaL_checkstring(L, 1));
diff --git a/nse_dnet.h b/nse_dnet.h
index 296f8db5e..5f0a216b4 100644
--- a/nse_dnet.h
+++ b/nse_dnet.h
@@ -3,6 +3,7 @@
LUALIB_API int l_dnet_new (lua_State *);
LUALIB_API int l_dnet_get_interface_link (lua_State *);
+LUALIB_API int l_dnet_get_interface_info (lua_State *);
LUALIB_API int luaopen_dnet (lua_State *L);
#endif
diff --git a/nse_nmaplib.cc b/nse_nmaplib.cc
index a274933d7..e2d6ecb56 100644
--- a/nse_nmaplib.cc
+++ b/nse_nmaplib.cc
@@ -741,6 +741,18 @@ static int l_address_family(lua_State *L)
return 1;
}
+/* return the interface name that was specified with
+ * the -e option
+ */
+static int l_get_interface (lua_State *L)
+{
+ if (*o.device)
+ lua_pushstring(L, o.device);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
int luaopen_nmap (lua_State *L)
{
static const luaL_reg nmaplib [] = {
@@ -767,6 +779,8 @@ int luaopen_nmap (lua_State *L)
{"is_privileged", l_is_privileged},
{"resolve", l_resolve},
{"address_family", l_address_family},
+ {"get_interface", l_get_interface},
+ {"get_interface_info", l_dnet_get_interface_info},
{NULL, NULL}
};
diff --git a/nselib/nmap.luadoc b/nselib/nmap.luadoc
index febf28758..ca43677ca 100644
--- a/nselib/nmap.luadoc
+++ b/nselib/nmap.luadoc
@@ -61,6 +61,54 @@ function resolve(host, family)
-- @usage local family = nmap.address_family()
function address_family()
+--- Returns the interface name (dnet-style) that Nmap is using.
+--
+-- For example in the pre-scanning ("prerule" scripts) phase
+-- if Nmap is run with the -e eth0, then "eth0" can be
+-- returned, however Nmap can return an other interface name since it
+-- can determine the best interface suited for the job.
+-- Other "hostrule" and "portrule" scripts
+-- should use the interface field of the host table:
+-- host.interface.
+--
+-- The result of this function can be used to get the interface information
+-- table, example: nmap.get_interface_info("eth0").
+--
+-- @return A string containing the interface name (dnet-style) on
+success, or a nil value on failures.
+-- @usage local interface_name = nmap.get_interface()
+function get_interface()
+
+--- Gets the interface network information.
+--
+-- This function takes a dnet-style interface name and returns a table
+-- containing the network information of the interface.
+--
+-- @param interface_name The name of the interface.
+-- @return Table containing the network information of the interface on
+-- success, or nil and an error message on failures.
+-- @usage local iface, err = nmap.get_interface_info("eth0")
+--
+-- Keys of the returned table:
+-- device The interface name, can be an interface aliase.
+-- shortname A simple short name of the device.
+-- netmask The netmask bits (CIDR) of the interface.
+-- address The string representing the IP address assigned
+-- to the interface.
+-- link The string representing the hardware type of the
+-- interface. Possible values are: "ethernet",
+-- "loopback", "p2p" or "other".
+-- mac MAC address (six-byte-long binary string) of the
+-- interface if the type of the interface is "ethernet",
+-- otherwise it is nil.
+-- broadcast The string representing the broadcast address
+-- assigned to the interface if the interface type is "ethernet"
+-- and if the used address is IPv4, otherwise it is nil.
+-- up The state of the interface, possible values are:
+-- "up" or "down".
+-- mtu The MTU size of the interface.
+function get_interface_info(interface_name)
+
--- Searches for the specified file and returns a string containing its path if
-- it is found and readable (to the process).
--