mirror of
https://github.com/nmap/nmap.git
synced 2026-05-13 08:46:45 +00:00
first build with ARP kung-fu, though far from finished with that feature
This commit is contained in:
parent
7e61d68a77
commit
3922128b12
14 changed files with 793 additions and 302 deletions
|
|
@ -1,4 +1,4 @@
|
|||
export NMAP_VERSION = 3.82
|
||||
export NMAP_VERSION = 3.82CSW
|
||||
NMAP_NAME= nmap
|
||||
NMAP_URL= http://www.insecure.org/nmap/
|
||||
NMAP_PLATFORM=@host@
|
||||
|
|
|
|||
15
Target.cc
15
Target.cc
|
|
@ -99,6 +99,7 @@
|
|||
***************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
#include <dnet.h>
|
||||
|
||||
#include "Target.h"
|
||||
#include "osscan.h"
|
||||
|
|
@ -125,7 +126,8 @@ void Target::Initialize() {
|
|||
targetipstring[0] = '\0';
|
||||
nameIPBuf = NULL;
|
||||
memset(&MACaddress, 0, sizeof(MACaddress));
|
||||
MACaddress_set = false;
|
||||
memset(&SrcMACaddress, 0, sizeof(SrcMACaddress));
|
||||
MACaddress_set = SrcMACaddress_set = false;
|
||||
htn.msecs_used = 0;
|
||||
htn.toclock_running = false;
|
||||
}
|
||||
|
|
@ -351,7 +353,18 @@ int Target::setMACAddress(const u8 *addy) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int Target::setSrcMACAddress(const u8 *addy) {
|
||||
if (!addy) return 1;
|
||||
memcpy(SrcMACaddress, addy, 6);
|
||||
SrcMACaddress_set = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the 6-byte long MAC address, or NULL if none has been set */
|
||||
const u8 *Target::MACAddress() {
|
||||
return (MACaddress_set)? MACaddress : NULL;
|
||||
}
|
||||
|
||||
const u8 *Target::SrcMACAddress() {
|
||||
return (SrcMACaddress_set)? SrcMACaddress : NULL;
|
||||
}
|
||||
|
|
|
|||
6
Target.h
6
Target.h
|
|
@ -176,8 +176,10 @@ class Target {
|
|||
|
||||
/* Takes a 6-byte MAC address */
|
||||
int setMACAddress(const u8 *addy);
|
||||
int setSrcMACAddress(const u8 *addy);
|
||||
/* Returns a pointer to 6-byte MAC address, or NULL if none is set */
|
||||
const u8 *MACAddress();
|
||||
const u8 *SrcMACAddress();
|
||||
|
||||
struct seq_info seq;
|
||||
FingerPrintResults *FPR;
|
||||
|
|
@ -189,7 +191,7 @@ class Target {
|
|||
int wierd_responses; /* echo responses from other addresses, Ie a network broadcast address */
|
||||
unsigned int flags; /* HOST_UP, HOST_DOWN, HOST_FIREWALLED, HOST_BROADCAST (instead of HOST_BROADCAST use wierd_responses */
|
||||
struct timeout_info to;
|
||||
char device[64]; /* The device we transmit on -- make sure to adjust some str* calls if I ever change this*/
|
||||
char device[64]; /* The device we transmit on -- make sure to adjust some str* calls if I ever change this size*/
|
||||
|
||||
private:
|
||||
char *hostname; // Null if unable to resolve or unset
|
||||
|
|
@ -206,6 +208,8 @@ class Target {
|
|||
char *nameIPBuf; /* for the NameIP(void) function to return */
|
||||
u8 MACaddress[6];
|
||||
bool MACaddress_set;
|
||||
u8 SrcMACaddress[6];
|
||||
bool SrcMACaddress_set;
|
||||
struct host_timeout_nfo htn;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -228,6 +228,6 @@ struct scan_lists {
|
|||
int prot_count;
|
||||
};
|
||||
|
||||
typedef enum { ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN } stype;
|
||||
typedef enum { ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP} stype;
|
||||
|
||||
#endif /*GLOBAL_STRUCTURES_H */
|
||||
|
|
|
|||
|
|
@ -908,8 +908,9 @@ T7(Resp=Y%DF=N%W=0%ACK=O%Flags=R%Ops=)
|
|||
PU(Resp=N)
|
||||
|
||||
# Apple AirPort Express (Apple Base Station V6.0)
|
||||
Fingerprint Apple AirPort Express WAP
|
||||
Fingerprint Apple AirPort Express WAP or Dell Fiber Channel Bridge Module
|
||||
Class Apple | embedded || WAP
|
||||
Class Dell | embedded || storage-misc
|
||||
TSeq(Class=RI%gcd=<6%SI=<A9830&>1000%TS=2HZ)
|
||||
T1(DF=Y%W=2000%ACK=S++%Flags=AS%Ops=MNWNNT)
|
||||
T2(Resp=N)
|
||||
|
|
|
|||
|
|
@ -1976,7 +1976,7 @@ match afs m|^[\d\D]{28}\s*(OpenAFS)\s+stable\s+([\d\.]+)\s+([^\0]+)\0| v/$1/$2/$
|
|||
match afs m|^[\d\D]{28}\s*(OpenAFS)([\d\.]{3}[^\s\0]*)\s+([^\0]+)\0| v/$1/$2/$3/
|
||||
match afs m|^[\d\D]{28}\s*(OpenAFS)([\d\.]{3}[^\s\0]*)\0| v/$1/$2//
|
||||
# Transarc AFS
|
||||
match afs m|^[\d\D]{28}\s*Base\sconfiguration\safs([\d\.]+)\s+([^\s\0\;]+)[\0\;]| v/Transarc AFS/$1/$2/
|
||||
match afs m|^[\d\D]{28}\s*Base\sconfiguration\safs([\d\.]+)\s+[^\s\0\;]+[\0\;]| v/Transarc AFS/$1/$2/
|
||||
# Arla
|
||||
match afs m|^[\d\D]{28}\s*arla-([\d\.]+)\0| v/Arla/$1//
|
||||
|
||||
|
|
|
|||
4
nmap.cc
4
nmap.cc
|
|
@ -601,6 +601,8 @@ int nmap_main(int argc, char *argv[]) {
|
|||
o.pingtype |= PINGTYPE_ICMP_TS;
|
||||
else if (*optarg == '0' || *optarg == 'N' || *optarg == 'D')
|
||||
o.pingtype = PINGTYPE_NONE;
|
||||
else if (*optarg == 'R')
|
||||
o.pingtype |= PINGTYPE_ARP;
|
||||
else if (*optarg == 'S') {
|
||||
o.pingtype |= (PINGTYPE_TCP|PINGTYPE_TCP_USE_SYN);
|
||||
if (isdigit((int) *(optarg+1)))
|
||||
|
|
@ -1792,6 +1794,8 @@ char *scantype2str(stype scantype) {
|
|||
case RPC_SCAN: return "RPCGrind Scan"; break;
|
||||
case MAIMON_SCAN: return "Maimon Scan"; break;
|
||||
case IPPROT_SCAN: return "IPProto Scan"; break;
|
||||
case PING_SCAN: return "Ping Scan"; break;
|
||||
case PING_SCAN_ARP: return "ARP Ping Scan"; break;
|
||||
default: assert(0); break;
|
||||
}
|
||||
|
||||
|
|
|
|||
1
nmap.h
1
nmap.h
|
|
@ -357,6 +357,7 @@ void *realloc();
|
|||
#define PINGTYPE_RAWTCP 128
|
||||
#define PINGTYPE_CONNECTTCP 256
|
||||
#define PINGTYPE_UDP 512
|
||||
#define PINGTYPE_ARP 1024
|
||||
|
||||
/* TCP/IP ISN sequence prediction classes */
|
||||
#define SEQ_UNKNOWN 0
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ int testno;
|
|||
int timeout;
|
||||
int avnum;
|
||||
unsigned int sequence_base;
|
||||
unsigned int openport;
|
||||
unsigned long openport;
|
||||
unsigned int bytes;
|
||||
unsigned int closedport = 31337;
|
||||
Port *tport = NULL;
|
||||
|
|
@ -227,7 +227,7 @@ snprintf(filter, sizeof(filter), "dst host %s and (icmp or (tcp and src host %s)
|
|||
}
|
||||
|
||||
if (o.verbose && openport != (unsigned long) -1)
|
||||
log_write(LOG_STDOUT, "For OSScan assuming port %d is open, %d is closed, and neither are firewalled\n", openport, closedport);
|
||||
log_write(LOG_STDOUT, "For OSScan assuming port %lu is open, %d is closed, and neither are firewalled\n", openport, closedport);
|
||||
|
||||
current_port = o.magic_port + NUM_SEQ_SAMPLES +1;
|
||||
|
||||
|
|
@ -422,7 +422,7 @@ if (o.verbose && openport != (unsigned long) -1)
|
|||
if ((tcp->th_flags & TH_RST)) {
|
||||
/* readtcppacket((char *) ip, ntohs(ip->ip_len));*/
|
||||
if (si->responses == 0) {
|
||||
fprintf(stderr, "WARNING: RST from port %hu -- is this port really open?\n", openport);
|
||||
fprintf(stderr, "WARNING: RST from port %lu -- is this port really open?\n", openport);
|
||||
/* We used to quit in this case, but left-overs from a SYN
|
||||
scan or lame-ass TCP wrappers can cause this! */
|
||||
}
|
||||
|
|
|
|||
582
scan_engine.cc
582
scan_engine.cc
File diff suppressed because it is too large
Load diff
|
|
@ -2100,10 +2100,10 @@ int service_scan(vector<Target *> &Targets) {
|
|||
bool plural = (Targets.size() != 1);
|
||||
if (!plural) {
|
||||
(*(Targets.begin()))->NameIP(targetstr, sizeof(targetstr));
|
||||
} else snprintf(targetstr, sizeof(targetstr), "%d hosts", Targets.size());
|
||||
} else snprintf(targetstr, sizeof(targetstr), "%u hosts", (unsigned) Targets.size());
|
||||
|
||||
log_write(LOG_STDOUT, "Initiating service scan against %d %s on %s at %02d:%02d\n",
|
||||
SG->services_remaining.size(),
|
||||
log_write(LOG_STDOUT, "Initiating service scan against %u %s on %s at %02d:%02d\n",
|
||||
(unsigned) SG->services_remaining.size(),
|
||||
(SG->services_remaining.size() == 1)? "service" : "services",
|
||||
targetstr, tm->tm_hour, tm->tm_min);
|
||||
}
|
||||
|
|
@ -2136,11 +2136,11 @@ int service_scan(vector<Target *> &Targets) {
|
|||
if (o.verbose) {
|
||||
gettimeofday(&now, NULL);
|
||||
if (SG->num_hosts_timedout == 0)
|
||||
log_write(LOG_STDOUT, "The service scan took %.2fs to scan %d %s on %d %s.\n",
|
||||
log_write(LOG_STDOUT, "The service scan took %.2fs to scan %u %s on %u %s.\n",
|
||||
TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0,
|
||||
SG->services_finished.size(),
|
||||
(unsigned) SG->services_finished.size(),
|
||||
(SG->services_finished.size() == 1)? "service" : "services",
|
||||
Targets.size(), (Targets.size() == 1)? "host" : "hosts");
|
||||
(unsigned) Targets.size(), (Targets.size() == 1)? "host" : "hosts");
|
||||
else log_write(LOG_STDOUT,
|
||||
"Finished service scan in %.2fs, but %d %s timed out.\n",
|
||||
TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0,
|
||||
|
|
|
|||
60
targets.cc
60
targets.cc
|
|
@ -107,6 +107,7 @@
|
|||
#include "NmapOps.h"
|
||||
#include "TargetGroup.h"
|
||||
#include "Target.h"
|
||||
#include "scan_engine.h"
|
||||
|
||||
extern NmapOps o;
|
||||
enum pingstyle { pingstyle_unknown, pingstyle_rawtcp, pingstyle_rawudp, pingstyle_connecttcp,
|
||||
|
|
@ -116,6 +117,7 @@ enum pingstyle { pingstyle_unknown, pingstyle_rawtcp, pingstyle_rawudp, pingstyl
|
|||
extern unsigned long flt_dsthost, flt_srchost;
|
||||
extern unsigned short flt_baseport;
|
||||
|
||||
|
||||
/* Gets the host number (index) of target in the hostbatch array of
|
||||
pointers. Note that the target MUST EXIST in the array or all
|
||||
heck will break loose. */
|
||||
|
|
@ -239,6 +241,44 @@ static int hostupdate(Target *hostbatch[], Target *target,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Conducts an ARP ping sweep of the given hosts to determine which ones
|
||||
are up on a local ethernet network */
|
||||
static void arpping(Target *hostbatch[], int num_hosts,
|
||||
struct scan_lists *ports) {
|
||||
/* First I change hostbatch into a vector<Target *>, which is what ultra_scan
|
||||
takes. I remove hosts that cannot be ARP scanned (such as localhost) */
|
||||
vector<Target *> targets;
|
||||
int targetno;
|
||||
targets.reserve(num_hosts);
|
||||
|
||||
for(targetno = 0; targetno < num_hosts; targetno++) {
|
||||
initialize_timeout_info(&hostbatch[targetno]->to);
|
||||
/* Default timout should be much lower for arp */
|
||||
hostbatch[targetno]->to.timeout = MIN(o.initialRttTimeout(), 100) * 1000;
|
||||
if (!hostbatch[targetno]->SrcMACAddress()) {
|
||||
bool islocal = islocalhost(hostbatch[targetno]->v4hostip());
|
||||
if (islocal) {
|
||||
log_write(LOG_STDOUT|LOG_NORMAL,
|
||||
"ARP ping: Considering %s UP because it is a local IP, despite no MAC address for device %s\n",
|
||||
hostbatch[targetno]->NameIP(), hostbatch[targetno]->device);
|
||||
hostbatch[targetno]->flags &= ~(HOST_DOWN|HOST_FIREWALLED);
|
||||
hostbatch[targetno]->flags |= HOST_UP;
|
||||
} else {
|
||||
log_write(LOG_STDOUT|LOG_NORMAL,
|
||||
"ARP ping: Considering %s DOWN because no MAC address found for device %s.\n",
|
||||
hostbatch[targetno]->NameIP(), hostbatch[targetno]->device);
|
||||
hostbatch[targetno]->flags &= ~HOST_FIREWALLED;
|
||||
hostbatch[targetno]->flags |= HOST_DOWN;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
targets.push_back(hostbatch[targetno]);
|
||||
}
|
||||
if (!targets.empty())
|
||||
ultra_scan(targets, ports, PING_SCAN_ARP);
|
||||
return;
|
||||
}
|
||||
|
||||
void hoststructfry(Target *hostbatch[], int nelem) {
|
||||
genfry((unsigned char *)hostbatch, sizeof(Target *), nelem);
|
||||
return;
|
||||
|
|
@ -291,7 +331,7 @@ do {
|
|||
3) We are doing a raw-mode portscan or osscan OR
|
||||
4) We are on windows and doing ICMP ping */
|
||||
if (o.isr00t && o.af() == AF_INET &&
|
||||
((*pingtype & (PINGTYPE_TCP|PINGTYPE_UDP)) || o.RawScan()
|
||||
((*pingtype & (PINGTYPE_TCP|PINGTYPE_UDP|PINGTYPE_ARP)) || o.RawScan()
|
||||
#ifdef WIN32
|
||||
|| (*pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS))
|
||||
#endif // WIN32
|
||||
|
|
@ -323,6 +363,11 @@ do {
|
|||
}
|
||||
}
|
||||
|
||||
/* If this is an ARP scan, we must determine the device's MAC address */
|
||||
if (*pingtype & PINGTYPE_ARP) {
|
||||
setTargetSrcMACAddressFromDevName(hs->hostbatch[hidx]);
|
||||
}
|
||||
|
||||
/* In some cases, we can only allow hosts that use the same device
|
||||
in a group. */
|
||||
if (o.af() == AF_INET && o.isr00t && hidx > 0 &&
|
||||
|
|
@ -336,7 +381,7 @@ do {
|
|||
goto batchfull;
|
||||
}
|
||||
hs->current_batch_sz++;
|
||||
}
|
||||
}
|
||||
|
||||
if (hs->current_batch_sz < hs->max_batch_sz &&
|
||||
hs->next_expression < hs->num_expressions) {
|
||||
|
|
@ -358,12 +403,19 @@ if (hs->randomize) {
|
|||
hoststructfry(hs->hostbatch, hs->current_batch_sz);
|
||||
}
|
||||
|
||||
/* Finally we do the mass ping (if required) */
|
||||
if ((*pingtype &
|
||||
/* First I'll do the ARP ping if necessary */
|
||||
if (*pingtype & PINGTYPE_ARP) {
|
||||
arpping(hs->hostbatch, hs->current_batch_sz, ports);
|
||||
}
|
||||
/* TODO: For efficiency, at some point it might be nice to usually do ARP
|
||||
ping before mass ping (and so get rid of else below) */
|
||||
/* Then we do the mass ping (if required - IP-level pings) */
|
||||
else if ((*pingtype &
|
||||
(PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS) ) ||
|
||||
((!o.isr00t || o.af() == AF_INET6 || hs->hostbatch[0]->v4host().s_addr) &&
|
||||
(*pingtype != PINGTYPE_NONE)))
|
||||
massping(hs->hostbatch, hs->current_batch_sz, ports, *pingtype);
|
||||
/* Otherwise -P0 so we just consider every host up */
|
||||
else for(i=0; i < hs->current_batch_sz; i++) {
|
||||
initialize_timeout_info(&hs->hostbatch[i]->to);
|
||||
hs->hostbatch[i]->flags |= HOST_UP; /*hostbatch[i].up = 1;*/
|
||||
|
|
|
|||
353
tcpip.cc
353
tcpip.cc
|
|
@ -100,7 +100,7 @@
|
|||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
#include <dnet.h>
|
||||
#include "tcpip.h"
|
||||
#include "NmapOps.h"
|
||||
|
||||
|
|
@ -206,6 +206,53 @@ char *getFinalPacketStats(char *buf, int buflen) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
/* Takes an ARP PACKET (including ethernet header) and prints it if
|
||||
packet tracing is enabled. 'frame' must point to the 14-byte
|
||||
ethernet header (e.g. starting with destination addr). The
|
||||
direction must be PacketTrace::SENT or PacketTrace::RCVD .
|
||||
Optional 'now' argument makes this function slightly more
|
||||
efficient by avoiding a gettimeofday() call. */
|
||||
void PacketTrace::traceArp(pdirection pdir, const u8 *frame, u32 len,
|
||||
struct timeval *now) {
|
||||
struct timeval tv;
|
||||
char arpdesc[128];
|
||||
char who_has[INET_ADDRSTRLEN], tell[INET_ADDRSTRLEN];
|
||||
|
||||
|
||||
if (pdir == SENT) {
|
||||
PktCt.sendPackets++;
|
||||
PktCt.sendBytes += len;
|
||||
} else {
|
||||
PktCt.recvPackets++;
|
||||
PktCt.recvBytes += len;
|
||||
}
|
||||
|
||||
if (!o.packetTrace()) return;
|
||||
|
||||
if (now)
|
||||
tv = *now;
|
||||
else gettimeofday(&tv, NULL);
|
||||
|
||||
if (len < 42) {
|
||||
error("Packet tracer: Arp packets must be at least 42 bytes long. Should be exactly that length excl. ethernet padding.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (frame[21] == 1) /* arp REQUEST */ {
|
||||
inet_ntop(AF_INET, frame+38, who_has, sizeof(who_has));
|
||||
inet_ntop(AF_INET, frame+28, tell, sizeof(who_has));
|
||||
snprintf(arpdesc, sizeof(arpdesc), "who-has %s tell %s", who_has, tell);
|
||||
} else { /* ARP REPLY */
|
||||
inet_ntop(AF_INET, frame+28, who_has, sizeof(who_has));
|
||||
snprintf(arpdesc, sizeof(arpdesc),
|
||||
"reply %s is-at %02X:%02X:%02X:%02X:%02X:%02X", who_has,
|
||||
frame[22], frame[23], frame[24], frame[25], frame[26], frame[27]);
|
||||
}
|
||||
|
||||
log_write(LOG_STDOUT|LOG_NORMAL, "%s (%.4fs) ARP %s\n", (pdir == SENT)? "SENT" : "RCVD", o.TimeSinceStartMS(&tv) / 1000.0, arpdesc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Takes an IP PACKET and prints it if packet tracing is enabled.
|
||||
'packet' must point to the IPv4 header. The direction must be
|
||||
|
|
@ -294,6 +341,11 @@ void PacketTrace::traceConnect(u8 proto, const struct sockaddr *sock,
|
|||
errbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Converts an IP address given in a sockaddr_storage to an IPv4 or
|
||||
IPv6 IP address string. Since a static buffer is returned, this is
|
||||
not thread-safe and can only be used once in calls like printf()
|
||||
|
|
@ -1321,96 +1373,6 @@ fcntl(sd, F_SETFL, options);
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Get the source address and interface name */
|
||||
#if 0
|
||||
char *getsourceif(struct in_addr *src, struct in_addr *dst) {
|
||||
int sd, sd2;
|
||||
u16 p1;
|
||||
struct sockaddr_in sock;
|
||||
int socklen = sizeof(struct sockaddr_in);
|
||||
struct sockaddr sa;
|
||||
recvfrom6_t sasize = sizeof(struct sockaddr);
|
||||
int ports, res;
|
||||
u8 buf[65536];
|
||||
struct timeval tv;
|
||||
unsigned int start;
|
||||
int data_offset, ihl, *intptr;
|
||||
int done = 0;
|
||||
|
||||
/* Get us some unreserved port numbers */
|
||||
get_random_bytes(&p1, 2);
|
||||
if (p1 < 5000) p1 += 5000;
|
||||
|
||||
if (!getuid()) {
|
||||
if ((sd2 = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) == -1)
|
||||
{perror("Linux Packet Socket troubles"); return 0;}
|
||||
unblock_socket(sd2);
|
||||
if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
{perror("Socket troubles"); return 0;}
|
||||
sock.sin_family = AF_INET;
|
||||
sock.sin_addr = *dst;
|
||||
sock.sin_port = htons(p1);
|
||||
if (connect(sd, (struct sockaddr *) &sock, sizeof(struct sockaddr_in)) == -1)
|
||||
{ perror("UDP connect()");
|
||||
close(sd);
|
||||
close(sd2);
|
||||
return NULL;
|
||||
}
|
||||
if (getsockname(sd, (SA *)&sock, &socklen) == -1) {
|
||||
perror("getsockname");
|
||||
close(sd);
|
||||
close(sd2);
|
||||
return NULL;
|
||||
}
|
||||
ports = (ntohs(sock.sin_port) << 16) + p1;
|
||||
#if ( TCPIP_DEBUGGING )
|
||||
printf("ports is %X\n", ports);
|
||||
#endif
|
||||
if (send(sd, "", 0, 0) == -1)
|
||||
fatal("Could not send UDP packet");
|
||||
start = time(NULL);
|
||||
do {
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
res = recvfrom(sd2, buf, 65535, 0, &sa, &sasize);
|
||||
if (res < 0) {
|
||||
if (socket_errno() != EWOULDBLOCK)
|
||||
perror("recvfrom");
|
||||
}
|
||||
if (res > 0) {
|
||||
#if ( TCPIP_DEBUGGING )
|
||||
printf("Got packet!\n");
|
||||
printf("sa.sa_data: %s\n", sa.sa_data);
|
||||
printf("Hex dump of packet (len %d):\n", res);
|
||||
hdump(buf, res);
|
||||
#endif
|
||||
data_offset = get_link_offset(sa.sa_data);
|
||||
ihl = (*(buf + data_offset) & 0xf) * 4;
|
||||
/* If it is big enough and it is IPv4 */
|
||||
if (res >= data_offset + ihl + 4 &&
|
||||
(*(buf + data_offset) & 0x40)) {
|
||||
intptr = (int *) ((char *) buf + data_offset + ihl);
|
||||
if (*intptr == ntohl(ports)) {
|
||||
intptr = (int *) ((char *) buf + data_offset + 12);
|
||||
#if ( TCPIP_DEBUGGING )
|
||||
printf("We've found our packet [krad]\n");
|
||||
#endif
|
||||
memcpy(src, buf + data_offset + 12, 4);
|
||||
close(sd);
|
||||
close(sd2);
|
||||
return strdup(sa.sa_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(!done && time(NULL) - start < 2);
|
||||
close(sd);
|
||||
close(sd2);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
int getsourceip(struct in_addr *src, const struct in_addr * const dst) {
|
||||
int sd;
|
||||
struct sockaddr_in sock;
|
||||
|
|
@ -1442,48 +1404,6 @@ int getsourceip(struct in_addr *src, const struct in_addr * const dst) {
|
|||
return 1; /* Calling function responsible for checking validity */
|
||||
}
|
||||
|
||||
#if 0
|
||||
int get_link_offset(char *device) {
|
||||
int sd;
|
||||
struct ifreq ifr;
|
||||
sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
|
||||
#if (defined(SIOCGIFHWADDR) && defined(ARPHRD_ETHER) &&
|
||||
defined(ARPHRD_METRICOM) && defined(ARPHRD_SLIP) && defined(ARPHRD_CSLIP)
|
||||
&& defined(ARPHRD_SLIP6) && defined(ARPHRD_PPP) &&
|
||||
defined(ARPHRD_LOOPBACK) )
|
||||
if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0 ) {
|
||||
fatal("Can't obtain link offset. What kind of interface are you using?");
|
||||
}
|
||||
close(sd);
|
||||
switch (ifr.ifr_hwaddr.sa_family) {
|
||||
case ARPHRD_ETHER: /* These two are standard ethernet */
|
||||
case ARPHRD_METRICOM:
|
||||
return 14;
|
||||
break;
|
||||
case ARPHRD_SLIP:
|
||||
case ARPHRD_CSLIP:
|
||||
case ARPHRD_SLIP6:
|
||||
case ARPHRD_CSLIP6:
|
||||
case ARPHRD_PPP:
|
||||
return 0;
|
||||
break;
|
||||
case ARPHRD_LOOPBACK: /* Loopback interface (obviously) */
|
||||
return 14;
|
||||
break;
|
||||
default:
|
||||
fatal("Unknown link layer device: %d", ifr.ifr_hwaddr.sa_family);
|
||||
}
|
||||
#else
|
||||
printf("get_link_offset called even though your host doesn't support it. Assuming Ethernet or Loopback connection (wild guess)\n");
|
||||
return 14;
|
||||
#endif
|
||||
/* Not reached */
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read an IP packet using libpcap . We return the packet and take
|
||||
a pcap descripter and a pointer to the packet length (which we set
|
||||
in the function. If you want a maximum length returned, you
|
||||
|
|
@ -1494,7 +1414,6 @@ exit(1);
|
|||
low values (and 0) degenerate to the timeout specified
|
||||
in pcap_open_live()
|
||||
*/
|
||||
|
||||
/* If rcvdtime is non-null and a packet is returned, rcvd will be
|
||||
filled with the time that packet was captured from the wire by
|
||||
pcap. If linknfo is not NULL, linknfo->headerlen and
|
||||
|
|
@ -1687,6 +1606,106 @@ bool pcap_recv_timeval_valid() {
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Attempts to read one IPv4/Ethernet ARP reply packet from the pcap
|
||||
descriptor pd. If it receives one, fills in sendermac (must pass
|
||||
in 6 bytes), senderIP, and rcvdtime (can be NULL if you don't care)
|
||||
and returns 1. If it times out and reads no arp requests, returns
|
||||
0. to_usec is the timeout period in microseconds. Use 0 to avoid
|
||||
blocking to the extent possible, and -1 to block forever. Returns
|
||||
-1 or exits if ther is an error. */
|
||||
int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac, struct in_addr *senderIP,
|
||||
long to_usec, struct timeval *rcvdtime) {
|
||||
static int warning = 0;
|
||||
int datalink;
|
||||
struct pcap_pkthdr head;
|
||||
u8 *p;
|
||||
int timedout = 0;
|
||||
int badcounter = 0;
|
||||
struct timeval tv_start, tv_end;
|
||||
|
||||
if (!pd) fatal("NULL packet device passed to readarp_reply_pcap");
|
||||
|
||||
if (to_usec < 0) {
|
||||
if (!warning) {
|
||||
warning = 1;
|
||||
error("WARNING: Negative timeout value (%lu) passed to readip_pcap() -- using 0", to_usec);
|
||||
}
|
||||
to_usec = 0;
|
||||
}
|
||||
|
||||
/* New packet capture device, need to recompute offset */
|
||||
if ( (datalink = pcap_datalink(pd)) < 0)
|
||||
fatal("Cannot obtain datalink information: %s", pcap_geterr(pd));
|
||||
|
||||
if (datalink != DLT_EN10MB)
|
||||
fatal("readarp_reply_pcap called on interfaces that is datatype %d rather than DLT_EN10MB (%d)", datalink, DLT_EN10MB);
|
||||
|
||||
if (to_usec > 0) {
|
||||
gettimeofday(&tv_start, NULL);
|
||||
}
|
||||
|
||||
do {
|
||||
#ifdef WIN32
|
||||
gettimeofday(&tv_end, NULL);
|
||||
to_left = MAX(1, (to_usec - TIMEVAL_SUBTRACT(tv_end, tv_start)) / 1000);
|
||||
// Set the timeout (BUGBUG: this is cheating)
|
||||
PacketSetReadTimeout(pd->adapter, to_left);
|
||||
#endif
|
||||
|
||||
p = (u8 *) pcap_next(pd, &head);
|
||||
|
||||
|
||||
if (p && head.caplen >= 42) { /* >= because Ethernet padding makes 60 */
|
||||
/* frame type 0x0806 (arp), hw type eth (0x0001), prot ip (0x0800),
|
||||
hw size (0x06), prot size (0x04) */
|
||||
if (memcmp(p + 12, "\x08\x06\x00\x01\x08\x00\x06\x04\x00\x02", 10) == 0) {
|
||||
memcpy(sendermac, p + 22, 6);
|
||||
/* I think alignment should allow this ... */
|
||||
senderIP->s_addr = *(u32 *) (p + 28) ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!p) {
|
||||
/* Should we timeout? */
|
||||
if (to_usec == 0) {
|
||||
timedout = 1;
|
||||
} else if (to_usec > 0) {
|
||||
gettimeofday(&tv_end, NULL);
|
||||
if (TIMEVAL_SUBTRACT(tv_end, tv_start) >= to_usec) {
|
||||
timedout = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* We'll be a bit patient if we're getting actual packets back, but
|
||||
not indefinitely so */
|
||||
if (badcounter++ > 50)
|
||||
timedout = 1;
|
||||
}
|
||||
} while(!timedout);
|
||||
|
||||
if (timedout) return 0;
|
||||
|
||||
if (rcvdtime) {
|
||||
// FIXME: I eventually need to figure out why Windows head.ts time is sometimes BEFORE the time I
|
||||
// sent the packet (which is according to gettimeofday() in nbase). For now, I will sadly have to
|
||||
// use gettimeofday() for Windows in this case
|
||||
// Actually I now allow .05 discrepancy. So maybe this isn't needed. I'll comment out for now.
|
||||
// Nope: it is still needed at least for Windows. Sometimes the time from he pcap header is a
|
||||
// COUPLE SECONDS before the gettimeofday() results :(.
|
||||
#if defined(WIN32) || defined(__amigaos__)
|
||||
gettimeofday(&tv_end, NULL);
|
||||
*rcvdtime = tv_end;
|
||||
#else
|
||||
*rcvdtime = head.ts;
|
||||
assert(head.ts.tv_sec);
|
||||
#endif
|
||||
}
|
||||
PacketTrace::traceArp(PacketTrace::RCVD, (u8 *) p, 42, rcvdtime);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* This function tries to determine the target's ethernet MAC address
|
||||
from a received packet as follows:
|
||||
|
|
@ -2452,3 +2471,69 @@ int IPProbe::storePacket(u8 *ippacket, u32 len) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
ArpProbe::ArpProbe() {
|
||||
packetbuflen = 0;
|
||||
packetbuf = NULL;
|
||||
Reset();
|
||||
}
|
||||
|
||||
void ArpProbe::Reset() {
|
||||
if (packetbuf)
|
||||
free(packetbuf);
|
||||
packetbuflen = 0;
|
||||
packetbuf = NULL;
|
||||
ipquery = NULL;
|
||||
}
|
||||
|
||||
ArpProbe::~ArpProbe() {
|
||||
if (packetbuf) {
|
||||
free(packetbuf);
|
||||
packetbuf = NULL;
|
||||
packetbuflen = 0;
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
int ArpProbe::storePacket(u8 *arppacket, u32 len) {
|
||||
assert(packetbuf == NULL);
|
||||
assert(len == 42);
|
||||
packetbuf = (u8 *) safe_malloc(len);
|
||||
memcpy(packetbuf, arppacket, len);
|
||||
packetbuflen = len;
|
||||
ipquery = (struct in_addr *) ((u8 *)arppacket + 38);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Finds MAC address of target->device and sets into target. Caches
|
||||
the results so that it will be really quick if you have many targets
|
||||
that send out with the same device, and you pass them roughly in
|
||||
order (only caches one). Returns -1 if cannot find the MAC address
|
||||
(often meaning this is localhost, or some other non-ethernet device.
|
||||
Returns 0 upon success. */
|
||||
int setTargetSrcMACAddressFromDevName(Target *target) {
|
||||
static u8 MAC_Cache[6];
|
||||
static char MAC_Cache_Dev[64] = {0};
|
||||
|
||||
assert(*target->device);
|
||||
if (strcmp(target->device, MAC_Cache_Dev) == 0)
|
||||
target->setSrcMACAddress(MAC_Cache);
|
||||
else {
|
||||
eth_t *e;
|
||||
eth_addr_t et;
|
||||
|
||||
assert(sizeof(et) >= 6);
|
||||
e = eth_open(target->device);
|
||||
if (!e)
|
||||
fatal("dnet: Failed to open ethernet device %s\n", target->device);
|
||||
if (eth_get(e, &et) == -1)
|
||||
return -1;
|
||||
// fatal("dnet: Failed to obtain HW MAC address for ethernet device %s\n", target->device);
|
||||
eth_close(e);
|
||||
Strncpy(MAC_Cache_Dev, target->device, sizeof(MAC_Cache_Dev));
|
||||
memcpy(MAC_Cache, (const char *) &et, 6);
|
||||
target->setSrcMACAddress(MAC_Cache);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
47
tcpip.h
47
tcpip.h
|
|
@ -295,6 +295,14 @@ class PacketTrace {
|
|||
static void traceConnect(u8 proto, const struct sockaddr *sock,
|
||||
int socklen, int connectrc, int connect_errno,
|
||||
const struct timeval *now);
|
||||
/* Takes an ARP PACKET (including ethernet header) and prints it if
|
||||
packet tracing is enabled. 'frame' must point to the 14-byte
|
||||
ethernet header (e.g. starting with destination addr). The
|
||||
direction must be PacketTrace::SENT or PacketTrace::RCVD .
|
||||
Optional 'now' argument makes this function slightly more
|
||||
efficient by avoiding a gettimeofday() call. */
|
||||
static void PacketTrace::traceArp(pdirection pdir, const u8 *frame, u32 len,
|
||||
struct timeval *now);
|
||||
};
|
||||
|
||||
class PacketCounter {
|
||||
|
|
@ -469,6 +477,26 @@ class IPProbe {
|
|||
void Reset();
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
/* Handles an *IPv4* Arp probe */
|
||||
class ArpProbe {
|
||||
public:
|
||||
ArpProbe();
|
||||
~ArpProbe();
|
||||
/* Takes an ARP packet and stores _a copy_ of it, in this Probe,
|
||||
adjusting proper header pointers and such. Then length better
|
||||
equal 42! */
|
||||
int storePacket(u8 *arppacket, u32 len);
|
||||
u32 packetbuflen; /* Length of the whole packet */
|
||||
u8 *packetbuf; /* The packet itself */
|
||||
struct in_addr *ipquery; /* IP address this ARP seeks */
|
||||
/* Resets everything to NULL. Frees packetbuf if it is filled. You
|
||||
can reuse a Probe by calling Reset() and then a new
|
||||
storePacket(). */
|
||||
void Reset();
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
/* This ideally should be a port that isn't in use for any protocol on our machine or on the target */
|
||||
|
|
@ -634,6 +662,15 @@ char *getFinalPacketStats(char *buf, int buflen);
|
|||
|
||||
int setTargetMACIfAvailable(Target *target, struct link_header *linkhdr,
|
||||
struct ip *ip, int overwrite);
|
||||
|
||||
/* Finds MAC address of target->device and sets into target. Caches
|
||||
the results so that it will be really quick if you have many targets
|
||||
that send out with the same device, and you pass them roughly in
|
||||
order (only caches one). Returns -1 if cannot find the MAC address
|
||||
(often meaning this is localhost, or some other non-ethernet device.
|
||||
Returns 0 upon success. */
|
||||
int setTargetSrcMACAddressFromDevName(Target *target);
|
||||
|
||||
int islocalhost(const struct in_addr * const addr);
|
||||
int unblock_socket(int sd);
|
||||
int Sendto(char *functionname, int sd, const unsigned char *packet, int len,
|
||||
|
|
@ -653,6 +690,16 @@ int get_link_offset(char *device);
|
|||
lnkinfo->header will be filled with the appropriate values. */
|
||||
char *readip_pcap(pcap_t *pd, unsigned int *len, long to_usec,
|
||||
struct timeval *rcvdtime, struct link_header *linknfo);
|
||||
/* Attempts to read one IPv4/Ethernet ARP reply packet from the pcap
|
||||
descriptor pd. If it receives one, fills in sendermac (must pass
|
||||
in 6 bytes), senderIP, and rcvdtime (can be NULL if you don't care)
|
||||
and returns 1. If it times out and reads no arp requests, returns
|
||||
0. to_usec is the timeout period in microseconds. Use 0 to avoid
|
||||
blocking to the extent possible, and -1 to block forever. Returns
|
||||
-1 or exits if ther is an error. */
|
||||
int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac, struct in_addr *senderIP,
|
||||
long to_usec, struct timeval *rcvdtime);
|
||||
|
||||
#ifndef HAVE_INET_ATON
|
||||
int inet_aton(register const char *, struct in_addr *);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue