From 5767158030f008fab6105bd7ca306978dbfd0449 Mon Sep 17 00:00:00 2001 From: dmiller Date: Tue, 16 Jun 2026 17:32:12 +0000 Subject: [PATCH] Reuse raw socket for IPv6 when possible --- FPEngine.cc | 2 +- idle_scan.cc | 2 +- libnetutil/netutil.cc | 20 +++++++------------- libnetutil/netutil.h | 4 ++-- nping/ProbeMode.cc | 2 +- osscan2.cc | 2 +- scan_engine.cc | 2 +- tcpip.h | 2 -- traceroute.cc | 2 +- 9 files changed, 15 insertions(+), 23 deletions(-) diff --git a/FPEngine.cc b/FPEngine.cc index fd1de6299..f1001dcbb 100644 --- a/FPEngine.cc +++ b/FPEngine.cc @@ -161,7 +161,7 @@ void FPNetworkControl::init(const char *ifname, devtype iftype) { netutil_eth_t *ethsd = NULL; /* Obtain raw socket or check that we can obtain an eth descriptor. */ - if (!raw_socket_or_eth(o.sendpref, ifname, iftype, &this->rawsd, ðsd)) { + if (!raw_socket_or_eth(o.sendpref, ifname, iftype, &this->rawsd, ðsd, AF_INET6)) { fatal("Couldn't obtain raw socket or eth handle in %s", __func__); } diff --git a/idle_scan.cc b/idle_scan.cc index 200aeeda2..55f78169b 100644 --- a/idle_scan.cc +++ b/idle_scan.cc @@ -587,7 +587,7 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName, /* Now lets send some probes to check IP ID algorithm ... */ /* First we need a raw socket ... */ if (!raw_socket_or_eth(o.sendpref, proxy->host.deviceName(), proxy->host.ifType(), - &proxy->rawsd, &proxy->eth.ethsd)) { + &proxy->rawsd, &proxy->eth.ethsd, proxy->host.af())) { fatal("%s: Failed to open raw socket or ethernet handle", __func__); } if (proxy->eth.ethsd != NULL) { diff --git a/libnetutil/netutil.cc b/libnetutil/netutil.cc index 7b609989a..bd41d6413 100644 --- a/libnetutil/netutil.cc +++ b/libnetutil/netutil.cc @@ -1236,7 +1236,7 @@ static void netutil_perror(const char *msg) { * Bind to an interface with SO_BINDTODEVICE (if device is not NULL). The socket is created with address family AF_INET, but may be usable for AF_INET6, depending on the operating system. */ -int netutil_raw_socket(const char *device) { +int netutil_raw_socket(const char *device, int af) { #ifdef WIN32 netutil_error("Windows does not have adequate raw socket support."); return -1; @@ -1244,7 +1244,7 @@ int netutil_raw_socket(const char *device) { int rawsd; int one = 1; - rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + rawsd = socket(af, SOCK_RAW, IPPROTO_RAW); if (rawsd < 0) { netutil_perror("Couldn't open a raw socket. " #if defined(sun) && defined(__SVR4) @@ -1266,7 +1266,7 @@ int netutil_raw_socket(const char *device) { } int raw_socket_or_eth(int sendpref, const char *ifname, devtype iftype, - int *rawsd, netutil_eth_t **ethsd) { + int *rawsd, netutil_eth_t **ethsd, int af) { assert(rawsd != NULL); *rawsd = -1; assert(ethsd != NULL); @@ -1317,7 +1317,7 @@ int raw_socket_or_eth(int sendpref, const char *ifname, devtype iftype, continue; } #endif - int sd = netutil_raw_socket(ifname); + int sd = netutil_raw_socket(ifname, af); if (sd >= 0) { *rawsd = sd; break; @@ -2790,14 +2790,12 @@ int send_frag_ip_packet(int sd, const struct eth_nfo *eth, /* Send an IPv6 packet over a raw socket, on platforms where IPPROTO_RAW implies IP_HDRINCL-like behavior. */ -static int send_ipv6_ipproto_raw(const struct sockaddr_in6 *dst, +static int send_ipv6_ipproto_raw(int sd, const struct sockaddr_in6 *dst, const unsigned char *packet, unsigned int packetlen) { - int sd, n; + int n; - sd = -1; n = -1; - sd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW); if (sd == -1) { perror("socket"); goto bail; @@ -2806,9 +2804,6 @@ static int send_ipv6_ipproto_raw(const struct sockaddr_in6 *dst, n = Sendto(__func__, sd, packet, packetlen, 0, (struct sockaddr *) dst, sizeof(*dst)); bail: - if (sd != -1) - close(sd); - return n; } @@ -2991,14 +2986,13 @@ bail: #endif -/* For now, the sd argument is ignored. */ int send_ipv6_packet_eth_or_sd(int sd, const struct eth_nfo *eth, const struct sockaddr_in6 *dst, const u8 *packet, unsigned int packetlen) { if (eth != NULL) { return send_ip_packet_eth(eth, packet, packetlen, AF_INET6); } else { #if HAVE_IPV6_IPPROTO_RAW - return send_ipv6_ipproto_raw(dst, packet, packetlen); + return send_ipv6_ipproto_raw(sd, dst, packet, packetlen); #elif !WIN32 return send_ipv6_ip(dst, packet, packetlen); #endif diff --git a/libnetutil/netutil.h b/libnetutil/netutil.h index b4f5c9497..2abf6fedd 100644 --- a/libnetutil/netutil.h +++ b/libnetutil/netutil.h @@ -318,7 +318,7 @@ void eth_close_cached(); * Bind to an interface with SO_BINDTODEVICE (if device is not NULL). The socket is created with address family AF_INET, but may be usable for AF_INET6, depending on the operating system. */ -int netutil_raw_socket(const char *device); +int netutil_raw_socket(const char *device, int af=AF_INET); /* How should we send raw IP packets? Nmap can generally use either ethernet or raw ip sockets. Which is better depends on platform @@ -338,7 +338,7 @@ int netutil_raw_socket(const char *device); #define PACKET_SEND_IP_STRONG 0x10 #define PACKET_SEND_IP (PACKET_SEND_IP_WEAK | PACKET_SEND_IP_STRONG) int raw_socket_or_eth(int sendpref, const char *ifname, devtype iftype, - int *rawsd, netutil_eth_t **ethsd); + int *rawsd, netutil_eth_t **ethsd, int af=AF_INET); /* Takes a protocol number like IPPROTO_TCP, IPPROTO_UDP, or * IPPROTO_IP and returns a ascii representation (or "unknown" if it diff --git a/nping/ProbeMode.cc b/nping/ProbeMode.cc index df4d79cbc..43fa3c939 100644 --- a/nping/ProbeMode.cc +++ b/nping/ProbeMode.cc @@ -304,7 +304,7 @@ int ProbeMode::start(){ if( o.getMode()!=ARP && o.sendEth()==false ){ /* Get socket descriptor. No need for it in ARP since we send at eth level */ - if ((rawipsd = netutil_raw_socket(o.getDevice())) < 0 ) + if ((rawipsd = netutil_raw_socket(o.getDevice(), o.ipv6() ? AF_INET6 : AF_INET)) < 0 ) nping_fatal(QT_3,"Couldn't acquire raw socket. Are you root?"); } diff --git a/osscan2.cc b/osscan2.cc index d967b788e..864e1605c 100644 --- a/osscan2.cc +++ b/osscan2.cc @@ -1344,7 +1344,7 @@ HostOsScan::HostOsScan(Target *t) { ethsd = NULL; int sendpref = o.sendpref; - if (!raw_socket_or_eth(sendpref, t->deviceName(), t->ifType(), &rawsd, ðsd)) { + if (!raw_socket_or_eth(sendpref, t->deviceName(), t->ifType(), &rawsd, ðsd, AF_INET)) { fatal("%s: Failed to open raw socket or ethernet device", __func__); } if (rawsd >= 0) diff --git a/scan_engine.cc b/scan_engine.cc index a0447b546..7fcd6bfee 100644 --- a/scan_engine.cc +++ b/scan_engine.cc @@ -964,7 +964,7 @@ void UltraScanInfo::Init(std::vector &Targets, const struct scan_lists sendpref = PACKET_SEND_ETH_WEAK; } if (!raw_socket_or_eth(sendpref, Targets[0]->deviceName(), Targets[0]->ifType(), - &rawsd, ðsd)) { + &rawsd, ðsd, Targets[0]->af())) { fatal("Couldn't open a raw socket or eth handle."); } /* Raw scan types also need to know the source IP. */ diff --git a/tcpip.h b/tcpip.h index e22cbd390..a00269bde 100644 --- a/tcpip.h +++ b/tcpip.h @@ -76,8 +76,6 @@ class Target; #define INET_ADDRSTRLEN 16 #endif -int nmap_raw_socket(); - /* Used for tracing all packets sent or received (eg the --packet-trace option) */ diff --git a/traceroute.cc b/traceroute.cc index 3559f1538..df801dc73 100644 --- a/traceroute.cc +++ b/traceroute.cc @@ -833,7 +833,7 @@ TracerouteState::TracerouteState(std::vector &targets) { assert(targets.size() > 0); if (!raw_socket_or_eth(o.sendpref, targets[0]->deviceName(), targets[0]->ifType(), - &rawsd, ðsd)) { + &rawsd, ðsd, targets[0]->af())) { fatal("traceroute: socket troubles"); }