From 271045501ff90943ce4885aacf33d53fa7c2d92f Mon Sep 17 00:00:00 2001 From: david Date: Sat, 15 Sep 2012 14:57:34 +0000 Subject: [PATCH] Make getNextHopMAC do ND when the dest is IPv6. This is what setTargetNextHopMAC already did, but the code change was not copied here. This provided a way for NSE scripts to cause an assertion failure: local math = require "math" local packet = require "packet" function portrule(host, port) return port.protocol == "udp" end function action(host, port) local ip_raw = bin.pack("H", "60000000000d11ff") .. host.bin_ip_src .. host.bin_ip .. bin.pack(">S", math.random(32768, 65535)) .. bin.pack(">S", port.number) .. bin.pack("H", "000d8082") .. "hello" local p = packet.Packet:new(ip_raw, #ip_raw) p:udp_count_checksum() local s = nmap.new_dnet() s:ip_open() s:ip_send(p.buf) end This would fail with the message "doArp can only handle IPv4 addresses" when ip_send called getNextHopMAC. (Only with --send-eth.) --- tcpip.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tcpip.cc b/tcpip.cc index ba094568d..01f258a6b 100644 --- a/tcpip.cc +++ b/tcpip.cc @@ -1967,11 +1967,11 @@ bool getNextHopMAC(const char *iface, const u8 *srcmac, const struct sockaddr_st arp_t *a; struct arp_entry ae; - /* Nmap's ARP cache */ + /* First, let us check the Nmap arp cache ... */ if (mac_cache_get(dstss, dstmac)) return true; - /* System ARP cache */ + /* Maybe the system ARP cache will be more helpful */ a = arp_open(); addr_ston((sockaddr *) dstss, &ae.arp_pa); if (arp_get(a, &ae) == 0) { @@ -1982,10 +1982,18 @@ bool getNextHopMAC(const char *iface, const u8 *srcmac, const struct sockaddr_st } arp_close(a); - /* Send ARP */ - if (doArp(iface, srcmac, srcss, dstss, dstmac, PacketTrace::traceArp)) { - mac_cache_set(dstss, dstmac); - return true; + /* OK, the last choice is to send our own damn ARP request (and + retransmissions if necessary) to determine the MAC */ + if (dstss->ss_family == AF_INET) { + if (doArp(iface, srcmac, srcss, dstss, dstmac, PacketTrace::traceArp)) { + mac_cache_set(dstss, dstmac); + return true; + } + } else if (dstss->ss_family == AF_INET6) { + if (doND(iface, srcmac, srcss, dstss, dstmac, PacketTrace::traceND)) { + mac_cache_set(dstss, dstmac); + return true; + } } return false;