mirror of
https://github.com/nmap/nmap.git
synced 2025-12-24 08:29:04 +00:00
Factor out Ethernet and socket sending function to avoid a big if-else
in send_ip_packet.
This commit is contained in:
80
tcpip.cc
80
tcpip.cc
@@ -1373,41 +1373,62 @@ do {
|
||||
return res;
|
||||
}
|
||||
|
||||
static int send_ip_packet_eth(struct eth_nfo *eth, u8 *packet, unsigned int packetlen);
|
||||
static int send_ip_packet_sd(int sd, u8 *packet, unsigned int packetlen);
|
||||
|
||||
/* Send a pre-built IPv4 packet */
|
||||
/* Send a pre-built IPv4 packet. Handles fragmentation and whether to send with
|
||||
an ethernet handle or a socket. */
|
||||
int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetlen) {
|
||||
struct sockaddr_in sock;
|
||||
int res;
|
||||
struct ip *ip = (struct ip *) packet;
|
||||
struct tcp_hdr *tcp = NULL;
|
||||
struct udp_hdr *udp;
|
||||
u8 *eth_frame = NULL;
|
||||
eth_t *ethsd;
|
||||
bool ethsd_opened = false;
|
||||
int res;
|
||||
|
||||
assert(packet);
|
||||
assert( (int) packetlen > 0);
|
||||
assert((int) packetlen > 0);
|
||||
|
||||
// fragmentation requested && packet is bigger than MTU
|
||||
if (o.fragscan && ( packetlen - ip->ip_hl * 4 > (unsigned int) o.fragscan ))
|
||||
return send_frag_ip_packet(sd, eth, packet, packetlen, o.fragscan);
|
||||
if (o.fragscan && (packetlen - ip->ip_hl * 4 > (unsigned int) o.fragscan))
|
||||
return send_frag_ip_packet(sd, eth, packet, packetlen, o.fragscan);
|
||||
|
||||
if (eth) {
|
||||
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)
|
||||
fatal("%s: Failed to open ethernet device (%s)", __func__, eth->devname);
|
||||
ethsd_opened = true;
|
||||
} else ethsd = eth->ethsd;
|
||||
res = eth_send(ethsd, eth_frame, 14 + packetlen);
|
||||
PacketTrace::trace(PacketTrace::SENT, packet, packetlen);
|
||||
/* No need to close ethsd due to caching */
|
||||
free(eth_frame);
|
||||
eth_frame = NULL;
|
||||
return res;
|
||||
if (eth)
|
||||
res = send_ip_packet_eth(eth, packet, packetlen);
|
||||
else
|
||||
res = send_ip_packet_sd(sd, packet, packetlen);
|
||||
|
||||
PacketTrace::trace(PacketTrace::SENT, packet, packetlen);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Send an IP packet over an ethernet handle. */
|
||||
static int send_ip_packet_eth(struct eth_nfo *eth, u8 *packet, unsigned int packetlen) {
|
||||
eth_t *ethsd;
|
||||
u8 *eth_frame;
|
||||
int res;
|
||||
|
||||
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)
|
||||
fatal("%s: Failed to open ethernet device (%s)", __func__, eth->devname);
|
||||
} else {
|
||||
ethsd = eth->ethsd;
|
||||
}
|
||||
res = eth_send(ethsd, eth_frame, 14 + packetlen);
|
||||
/* No need to close ethsd due to caching */
|
||||
free(eth_frame);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Send an IP packet over a raw socket. */
|
||||
static int send_ip_packet_sd(int sd, u8 *packet, unsigned int packetlen) {
|
||||
struct sockaddr_in sock;
|
||||
struct ip *ip = (struct ip *) packet;
|
||||
struct tcp_hdr *tcp;
|
||||
struct udp_hdr *udp;
|
||||
int res;
|
||||
|
||||
assert(sd >= 0);
|
||||
memset(&sock, 0, sizeof(sock));
|
||||
@@ -1415,6 +1436,7 @@ int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetl
|
||||
#if HAVE_SOCKADDR_SA_LEN
|
||||
sock.sin_len = sizeof(sock);
|
||||
#endif
|
||||
|
||||
/* It is bogus that I need the address and port info when sending a RAW IP
|
||||
packet, but it doesn't seem to work w/o them */
|
||||
if (packetlen >= 20) {
|
||||
@@ -1439,7 +1461,7 @@ int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetl
|
||||
#endif
|
||||
|
||||
res = Sendto("send_ip_packet", sd, packet, packetlen, 0,
|
||||
(struct sockaddr *)&sock, (int)sizeof(struct sockaddr_in));
|
||||
(struct sockaddr *) &sock, (int) sizeof(struct sockaddr_in));
|
||||
|
||||
/* Undo the byte order switching. */
|
||||
#if FREEBSD || BSDI || NETBSD || DEC || MACOSX
|
||||
@@ -1447,8 +1469,6 @@ int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetl
|
||||
ip->ip_off = htons(ip->ip_off);
|
||||
#endif
|
||||
|
||||
PacketTrace::trace(PacketTrace::SENT, packet, packetlen);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user