From a4a046ac4cf5530e34b5fca68b996fe33eed4c85 Mon Sep 17 00:00:00 2001 From: david Date: Sat, 15 Sep 2012 17:56:19 +0000 Subject: [PATCH] Let dnet:ip_send take a destination address. Previously we always took the destination address from the packet buffer, which failed for IPv6 link-local addresses because the packet buffer does not contain the scope id. --- CHANGELOG | 7 +++++++ nse_dnet.cc | 27 ++++++++++++++++++++------- nselib/nmap.luadoc | 8 ++++++-- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d04a811ee..fe9919eb5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,12 @@ # Nmap Changelog ($Id$); -*-text-*- +o [NSE] The nmap.ip_send function now takes a second argument, the + destination to send to. Previously the destination address was taken + from the packet buffer, but this failed for IPv6 link-local + addresses, because the scope ID is not part of the packet. Calling + ip_send without a destination address will continue to use the old + behavior, but this practice is deprecated. + o Added http fingerprints for Sitecore CMS. [Jesper Kückelhahn] o Increased portability of configure scripts on systems using a libc diff --git a/nse_dnet.cc b/nse_dnet.cc index 22590e00d..95c275123 100644 --- a/nse_dnet.cc +++ b/nse_dnet.cc @@ -211,8 +211,10 @@ static int ip_close (lua_State *L) static int ip_send (lua_State *L) { struct abstract_ip_hdr hdr; + struct sockaddr_storage dst; nse_dnet_udata *udata = (nse_dnet_udata *) nseU_checkudata(L, 1, DNET_METATABLE, "dnet"); const char *packet; + const char *addr, *targetname; size_t packetlen; unsigned int payloadlen; char dev[16]; @@ -222,14 +224,25 @@ static int ip_send (lua_State *L) return luaL_error(L, "raw socket not open to send"); packet = luaL_checklstring(L, 2, &packetlen); + nseU_opttarget(L, 3, &addr, &targetname); - /* Extract src and dst from packet contents. */ - /* TODO: This doesn't work for link-local IPv6 addresses; there's no way to - recover the scope_id from the packet contents. */ payloadlen = packetlen; if (ip_get_data_any(packet, &payloadlen, &hdr) == NULL) return luaL_error(L, "can't parse ip packet"); + if (addr == NULL) { + /* Extract dst from packet contents. This is deprecated because it doesn't + work for link-local IPv6 addresses; there's no way to recover the + scope_id from the packet contents. */ + dst = hdr.dst; + } else { + /* Resolve hostname or numeric IP. */ + size_t dstlen; + int rc = resolve(addr, 0, &dst, &dstlen, AF_UNSPEC); + if (rc != 0) + return nseU_safeerror(L, gai_strerror(rc)); + } + *dev = '\0'; if (o.sendpref & PACKET_SEND_ETH) @@ -239,7 +252,7 @@ static int ip_send (lua_State *L) u8 dstmac[6]; eth_nfo eth; - if (!nmap_route_dst(&hdr.dst, &route)) + if (!nmap_route_dst(&dst, &route)) goto usesock; Strncpy(dev, route.ii.devname, sizeof(dev)); @@ -252,7 +265,7 @@ static int ip_send (lua_State *L) */ if (route.direct_connect) - nexthop = &hdr.dst; + nexthop = &dst; else nexthop = &route.nexthop; @@ -274,14 +287,14 @@ static int ip_send (lua_State *L) udata->eth = eth.ethsd = open_eth_cached(L, 1, route.ii.devname); - ret = send_ip_packet(udata->sock, ð, &hdr.dst, (u8 *) packet, lua_rawlen(L, 2)); + ret = send_ip_packet(udata->sock, ð, &dst, (u8 *) packet, lua_rawlen(L, 2)); } else { usesock: #ifdef WIN32 if (strlen(dev) > 0) win32_fatal_raw_sockets(dev); #endif - ret = send_ip_packet(udata->sock, NULL, &hdr.dst, (u8 *) packet, lua_rawlen(L, 2)); + ret = send_ip_packet(udata->sock, NULL, &dst, (u8 *) packet, lua_rawlen(L, 2)); } if (ret == -1) return nseU_safeerror(L, "error while sending: %s (errno %d)", diff --git a/nselib/nmap.luadoc b/nselib/nmap.luadoc index 4d9699b18..65e856e34 100644 --- a/nselib/nmap.luadoc +++ b/nselib/nmap.luadoc @@ -779,9 +779,13 @@ function ip_open() -- packet must begin with an IP header. If there was no previous valid call -- to ip_open an error is thrown. -- @param packet An IP packet to send. +-- @param dst A destination address, as a host table or string. If omitted, the +-- destination address is read from the packet; however this is deprecated, because +-- the packet does not contain the scope ID required to send to certain IPv6 +-- addresses. -- @see new_dnet --- @usage dnet:ip_send(packet) -function ip_send(packet) +-- @usage dnet:ip_send(packet, dst) +function ip_send(packet, dst) --- Closes a raw IPv4 socket. -- @see new_dnet, ip_open