8000 [pull] master from nmap:master by pull[bot] · Pull Request #783 · security-geeks/nmap · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[pull] master from nmap:master #783

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 145 additions & 45 deletions libnetutil/netutil.cc
< 9E81 td class="blob-code blob-code-context js-file-line"> const struct sockaddr_in *targetsin = (struct sockaddr_in *) targetip;
Original file line number Diff line number Diff line change
Expand Up @@ -959,10 +959,91 @@ int pcap_select(pcap_t *p, long usecs) {
return ret;
}

struct netutil_eth_t {
union {
pcap_t *pt;
eth_t *ethsd;
};
int datalink;
};

int netutil_eth_datalink(const netutil_eth_t *e) {
if (e) return e->datalink;
return -1;
}

#ifdef WIN32
#define eth_handle(_eth) (_eth->pt)
#define eth_handle_send pcap_inject
#define eth_handle_close eth_close
#else
#define eth_handle(_eth) (_eth->ethsd)
#define eth_handle_send eth_send
#define eth_handle_close eth_close
#endif

netutil_eth_t *netutil_eth_open(const char *device) {
assert(device != NULL);
assert(device[0] != '\0');

netutil_eth_t *e = (netutil_eth_t *)safe_zalloc(sizeof(netutil_eth_t));
e->datalink = -1;

#ifdef WIN32
char err0r[PCAP_ERRBUF_SIZE] = {0};
char pcapdev[128] = {0};
int failed = 0;
pcap_t *pt = NULL;
do {
if (!DnetName2PcapName(device, pcapdev, sizeof(pcapdev))) {
break;
}
pt = pcap_create(pcapdev, err0r);
if (!pt) {
netutil_error("pcap_create(%s) FAILED: %s.", pcapdev, err0r);
break;
}
failed = pcap_activate(pt);
if (failed < 0) {
// PCAP error
netutil_error("pcap_activate(%s) FAILED: %s.", pcapdev, pcap_geterr(pt));
pcap_close(pt);
return NULL;
}
else if (failed > 0) {
// PCAP warning, report but assume it'll still work
netutil_error("pcap_activate(%s) WARNING: %s.", pcapdev, pcap_geterr(pt));
}
eth_handle(e) = pt;
e->datalink = pcap_datalink(pt);
} while (0);
#else
eth_handle(e) = eth_open(device);
e->datalink = DLT_EN10MB;
#endif

if (eth_handle(e) == NULL) {
free(e);
return NULL;
}
return e;
}

void netutil_eth_close(netutil_eth_t *e) { 8000
assert(e != NULL);
eth_handle_close(eth_handle(e));
free(e);
}

ssize_t netutil_eth_send(netutil_eth_t *e, const void *buf, size_t len) {
assert(e != NULL);
assert(eth_handle(e) != NULL);
return eth_handle_send(eth_handle(e), buf, len);
}

/* These two are for eth_open_cached() and eth_close_cached() */
static char etht_cache_device_name[64];
static eth_t *etht_cache_device = NULL;
static netutil_eth_t *etht_cache_device = NULL;

/* A simple function that caches the eth_t from dnet for one device,
to avoid opening, closing, and re-opening it thousands of tims. If
Expand All @@ -972,7 +1053,7 @@ static eth_t *etht_cache_device = NULL;
eth_close() A DEVICE OBTAINED FROM THIS FUNCTION. Instead, you can
call eth_close_cached() to close whichever device (if any) is
cached. Returns NULL if it fails to open the device. */
eth_t *eth_open_cached(const char *device) {
netutil_eth_t *eth_open_cached(const char *device) {
if (!device)
netutil_fatal("%s() called with NULL device name!", __func__);
if (!*device)
Expand All @@ -984,12 +1065,12 @@ eth_t *eth_open_cached(const char *device) {
}

if (*etht_cache_device_name) {
eth_close(etht_cache_device);
netutil_eth_close(etht_cache_device);
etht_cache_device_name[0] = '\0';
etht_cache_device = NULL;
}

etht_cache_device = eth_open(device);
etht_cache_device = netutil_eth_open(device);
if (etht_cache_device)
Strncpy(etht_cache_device_name, device,
sizeof(etht_cache_device_name));
Expand All @@ -1000,7 +1081,7 @@ eth_t *eth_open_cached(const char *device) {
/* See the description for eth_open_cached */
void eth_ 10000 close_cached() {
if (etht_cache_device) {
eth_close(etht_cache_device);
netutil_eth_close(etht_cache_device);
etht_cache_device = NULL;
etht_cache_device_name[0] = '\0';
}
Expand Down Expand Up @@ -3448,26 +3529,70 @@ int Sendto(const char *functionname, int sd,
}


int netutil_eth_can_send(const netutil_eth_t *e) {
switch (netutil_eth_datalink(e)) {
case DLT_NULL:
case DLT_EN10MB:
case DLT_RAW:
return 1;
break;
default:
return 0;
break;
}
}

/* Send an IP packet over an ethernet handle. */
int send_ip_packet_eth(const struct eth_nfo *eth, const u8 *packet, unsigned int packetlen) {
eth_t *ethsd;
u8 *eth_frame;
static int send_ip_packet_eth(const struct eth_nfo *eth, const u8 *packet, unsigned int packetlen, int af) {
netutil_eth_t *ethsd;
u8 *eth_frame = NULL;
int res;
size_t framelen;
uint16_t ethertype = (af == AF_INET6 ? ETH_TYPE_IPV6 : ETH_TYPE_IP);

eth_frame = (u8 *) safe_malloc(14 + packetlen);
memcpy(eth_frame + 14, packet, packetlen);
eth_pack_hdr(eth_frame, eth->dstmac, eth->srcmac, ETH_TYPE_IP);
if (!eth->ethsd) {
ethsd = eth_open_cached(eth->devname);
if (!ethsd)
netutil_fatal("%s: Failed to open ethernet device (%s)", __func__, eth->devname);
} else {
ethsd = eth->ethsd;
}
res = eth_send(ethsd, eth_frame, 14 + packetlen);
switch (ethsd->datalink) {
case DLT_EN10MB:
framelen = 14 + packetlen;
eth_frame = (u8 *) safe_malloc(framelen);
memcpy(eth_frame + 14, packet, packetlen);
eth_pack_hdr(eth_frame, eth->dstmac, eth->srcmac, ethertype);
break;
case DLT_NULL:
framelen = 4 + packetlen;
eth_frame = (u8 *) safe_malloc(framelen);
memcpy(eth_frame + 4, packet, packetlen);
if (af == AF_INET6) {
/* These values are per libpcap/gencode.c */
#if defined(__APPLE__)
*(uint32_t *)eth_frame = 30; // macOS, iOS, other Darwin-based OSes
#elif defined(__FreeBSD__)
*(uint32_t *)eth_frame = 28; // FreeBSD
#else
*(uint32_t *)eth_frame = 24; // NetBSD, OpenBSD, BSD/OS, Npcap
#endif
}
else {
*(uint32_t *)eth_frame = AF_INET;
}
break;
case DLT_RAW:
framelen = packetlen;
break;
default:
netutil_fatal("%s: unsupported DLT for %s: %d", __func__, eth->devname, ethsd->datalink);
break;
}
res = netutil_eth_send(ethsd, eth_frame ? eth_frame : packet, framelen);
/* No need to close ethsd due to caching */
free(eth_frame);
if (eth_frame != packet)
free(eth_frame);

return res;
}
Expand Down Expand Up @@ -3531,7 +3656,7 @@ int send_ip_packet_eth_or_sd(int sd, const struct eth_nfo *eth,
const struct sockaddr_in *dst,
const u8 *packet, unsigned int packetlen) {
if(eth)
return send_ip_packet_eth(eth, packet, packetlen);
return send_ip_packet_eth(eth, packet, packetlen, AF_INET);
else
return send_ip_packet_sd(sd, dst, packet, packetlen);
}
Expand Down Expand Up 8000 @@ -3588,7 +3713,7 @@ int send_frag_ip_packet(int sd, const struct eth_nfo *eth,

/* There are three ways to send a raw IPv6 packet.

send_ipv6_eth works when the device is Ethernet. (Unfortunately IPv6-in-IPv4
send_ip_packet_eth works when the device is Ethernet. (Unfortunately IPv6-in-IPv4
tunnels are not.) We can control all header fields and extension headers.

send_ipv6_ipproto_raw must be used when IPPROTO_RAW sockets include the IP
Expand All @@ -3603,31 +3728,6 @@ int send_frag_ip_packet(int sd, const struct eth_nfo *eth,
protocol. (More precisely, one socket per distinct Next Header value.)
*/

/* Send an IPv6 packet over an Ethernet handle. */
static int send_ipv6_eth(const struct eth_nfo *eth, const u8 *packet, unsigned int packetlen) {
eth_t *ethsd;
struct eth_hdr *eth_frame;
u8 *copy;
int res;

copy = (u8 *) safe_malloc(packetlen + sizeof(*eth_frame));
memcpy(copy + sizeof(*eth_frame), packet, packetlen);
eth_frame = (struct eth_hdr *) copy;
eth_pack_hdr(eth_frame, eth->dstmac, eth->srcmac, ETH_TYPE_IPV6);
if (!eth->ethsd) {
ethsd = eth_open_cached(eth->devname);
if (!ethsd)
netutil_fatal("%s: Failed to open ethernet device (%s)", __func__, eth->devname);
} else {
ethsd = eth->ethsd;
}
res = eth_send(ethsd, eth_frame, sizeof(*eth_frame) + packetlen);
/* No need to close ethsd due to caching */
free(eth_frame);

return res;
}

#if HAVE_IPV6_IPPROTO_RAW

/* Send an IPv6 packet over a raw socket, on platforms where IPPROTO_RAW implies
Expand Down Expand Up @@ -3837,7 +3937,7 @@ static int send_ipv6_ip(const struct sockaddr_in6 *dst,
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_ipv6_eth(eth, packet, packetlen);
return send_ip_packet_eth(eth, packet, packetlen, AF_INET6);
} else {
#if HAVE_IPV6_IPPROTO_RAW
return send_ipv6_ipproto_raw(dst, packet, packetlen);
Expand Down Expand Up @@ -4386,7 +4486,7 @@ bool doND(const char *dev, const u8 *srcmac,
int timeouts[] = { 100000, 400000, 800000 };
int max_sends = 3;
int num_sends = 0; // How many we have sent so far
eth_t *ethsd;
netutil_eth_t *ethsd;
u8 frame[ETH_HDR_LEN + IP6_HDR_LEN + ICMPV6_HDR_LEN + 4 + 16 + 8];
struct timeval start, now, rcvdtime;
int timeleft;
Expand Down Expand Up @@ -4445,7 +4545,7 @@ bool doND(const char *dev, const u8 *srcmac,

while (!foundit && num_sends < max_sends) {
/* Send the sucker */
rc = eth_send(ethsd, frame, sizeof(frame));
rc = netutil_eth_send(ethsd, frame, sizeof(frame));
if (rc != sizeof(frame)) {
netutil_error("WARNING: %s: eth_send of Neighbor Solicitation packet returned %u rather than expected %d bytes", __func__, rc, (int) sizeof(frame));
}
Expand Down Expand Up @@ -4506,7 +4606,7 @@ bool doArp(const char *dev, const u8 *srcmac,
int timeouts[] = { 100000, 400000, 800000 };
int max_sends = 3;
int num_sends = 0; // How many we have sent so far
eth_t *ethsd;
netutil_eth_t *ethsd;
u8 frame[ETH_HDR_LEN + ARP_HDR_LEN + ARP_ETHIP_LEN];
const struct sockaddr_in *srcsin = (struct sockaddr_in *) srcip;
Expand Down Expand Up @@ -4542,7 +4642,7 @@ bool doArp(const char *dev, const u8 *srcmac,

while (!foundit && num_sends < max_sends) {
/* Send the sucker */
rc = eth_send(ethsd, frame, sizeof(frame));
rc = netutil_eth_send(ethsd, frame, sizeof(frame));
if (rc != sizeof(frame)) {
netutil_error("WARNING: %s: eth_send of ARP packet returned %u rather than expected %d bytes", __func__, rc, (int) sizeof(frame));
}
Expand Down
16 changes: 10 additions & 6 deletions libnetutil/netutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ extern "C" {
}
#endif

#include "dnet.h"
#include <nbase.h>
#include <dnet.h>

/* It is VERY important to never change the value of these two constants.
* Specially, OP_FAILURE should never be positive, as some pieces of code take
Expand Down Expand Up @@ -278,10 +278,12 @@ struct sys_route {
int metric;
};

struct netutil_eth_t;

struct eth_nfo {
F438 char srcmac[6];
char dstmac[6];
eth_t *ethsd; // Optional, but improves performance. Set to NULL if unavail
netutil_eth_t *ethsd; // Optional, but improves performance. Set to NULL if unavail
char devname[16]; // Only needed if ethsd is NULL.
};

Expand All @@ -293,7 +295,12 @@ struct eth_nfo {
eth_close() A DEVICE OBTAINED FROM THIS FUNCTION. Instead, you can
call eth_close_cached() to close whichever device (if any) is
cached. Returns NULL if it fails to open the device. */
eth_t *eth_open_cached(const char *device);
netutil_eth_t *eth_open_cached(const char *device);
netutil_eth_t *netutil_eth_open(const char *device);
void netutil_eth_close(netutil_eth_t *e);
ssize_t netutil_eth_send(netutil_eth_t *e, const void *buf, size_t len);
int netutil_eth_datalink(const netutil_eth_t *e);
int netutil_eth_can_send(const netutil_eth_t *e);

/* See the description for eth_open_cached */
void eth_close_cached();
Expand Down Expand Up @@ -424,9 +431,6 @@ int route_dst(const struct sockaddr_storage *dst, struct route_nfo *rnfo,
/* Send an IP packet over a raw socket. */
int send_ip_packet_sd(int sd, const struct sockaddr_in *dst, const u8 *packet, unsigned int packetlen);

/* Send an IP packet over an ethernet handle. */
int send_ip_packet_eth(const struct eth_nfo *eth, const u8 *packet, unsigned int packetlen);

/* Sends the supplied pre-built IPv4 packet. The packet is sent through
* the raw socket "sd" if "eth" is NULL. Otherwise, it gets sent at raw
* ethernet level. */
Expand Down
5 changes: 2 additions & 3 deletions nping/utils_net.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
#include "output.h"
#include "nbase.h"
#include "pcap.h"
#include "dnet.h"
#include <vector>

extern NpingOps o;
Expand Down Expand Up @@ -1111,8 +1110,8 @@ int send_packet(NpingTarget *target, int rawfd, u8 *pkt, size_t pktLen){
assert(pktLen > 0);

if ( o.sendEth() ){
eth_t *ethsd = eth_open_cached(o.getDevice());
eth_send(ethsd, pkt, pktLen);
netutil_eth_t *ethsd = eth_open_cached(o.getDevice());
netutil_eth_send(ethsd, pkt, pktLen);
}else{
if( o.ipv6() ){ /* IPv6 */
memset(&s6, 0, sizeof(struct sockaddr_in6));
Expand Down
Loading
0