Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
nmap
GitHub Repository: nmap/nmap
Path: blob/master/Target.cc
3730 views
1
2
/***************************************************************************
3
* Target.cc -- The Target class encapsulates much of the information Nmap *
4
* has about a host. Results (such as ping, OS scan, etc) are stored in *
5
* this class as they are determined. *
6
* *
7
***********************IMPORTANT NMAP LICENSE TERMS************************
8
*
9
* The Nmap Security Scanner is (C) 1996-2025 Nmap Software LLC ("The Nmap
10
* Project"). Nmap is also a registered trademark of the Nmap Project.
11
*
12
* This program is distributed under the terms of the Nmap Public Source
13
* License (NPSL). The exact license text applying to a particular Nmap
14
* release or source code control revision is contained in the LICENSE
15
* file distributed with that version of Nmap or source code control
16
* revision. More Nmap copyright/legal information is available from
17
* https://nmap.org/book/man-legal.html, and further information on the
18
* NPSL license itself can be found at https://nmap.org/npsl/ . This
19
* header summarizes some key points from the Nmap license, but is no
20
* substitute for the actual license text.
21
*
22
* Nmap is generally free for end users to download and use themselves,
23
* including commercial use. It is available from https://nmap.org.
24
*
25
* The Nmap license generally prohibits companies from using and
26
* redistributing Nmap in commercial products, but we sell a special Nmap
27
* OEM Edition with a more permissive license and special features for
28
* this purpose. See https://nmap.org/oem/
29
*
30
* If you have received a written Nmap license agreement or contract
31
* stating terms other than these (such as an Nmap OEM license), you may
32
* choose to use and redistribute Nmap under those terms instead.
33
*
34
* The official Nmap Windows builds include the Npcap software
35
* (https://npcap.com) for packet capture and transmission. It is under
36
* separate license terms which forbid redistribution without special
37
* permission. So the official Nmap Windows builds may not be redistributed
38
* without special permission (such as an Nmap OEM license).
39
*
40
* Source is provided to this software because we believe users have a
41
* right to know exactly what a program is going to do before they run it.
42
* This also allows you to audit the software for security holes.
43
*
44
* Source code also allows you to port Nmap to new platforms, fix bugs, and
45
* add new features. You are highly encouraged to submit your changes as a
46
* Github PR or by email to the [email protected] mailing list for possible
47
* incorporation into the main distribution. Unless you specify otherwise, it
48
* is understood that you are offering us very broad rights to use your
49
* submissions as described in the Nmap Public Source License Contributor
50
* Agreement. This is important because we fund the project by selling licenses
51
* with various terms, and also because the inability to relicense code has
52
* caused devastating problems for other Free Software projects (such as KDE
53
* and NASM).
54
*
55
* The free version of Nmap is distributed in the hope that it will be
56
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
57
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties,
58
* indemnification and commercial support are all available through the
59
* Npcap OEM program--see https://nmap.org/oem/
60
*
61
***************************************************************************/
62
63
/* $Id$ */
64
65
#ifdef WIN32
66
#include "nmap_winconfig.h"
67
#endif
68
69
#include "Target.h"
70
#include "FingerPrintResults.h" /* for ~FingerPrintResults() */
71
#include <dnet.h>
72
#include "nbase.h"
73
#include "NmapOps.h"
74
#include "nmap.h"
75
#include "nmap_error.h"
76
77
extern NmapOps o;
78
79
Target::Target() {
80
hostname = NULL;
81
targetname = NULL;
82
memset(&seq, 0, sizeof(seq));
83
distance = -1;
84
distance_calculation_method = DIST_METHOD_NONE;
85
FPR = NULL;
86
osscan_flag = OS_NOTPERF;
87
weird_responses = flags = 0;
88
traceroute_probespec.type = PS_NONE;
89
memset(&to, 0, sizeof(to));
90
memset(&targetsock, 0, sizeof(targetsock));
91
memset(&sourcesock, 0, sizeof(sourcesock));
92
memset(&nexthopsock, 0, sizeof(nexthopsock));
93
targetsocklen = sourcesocklen = nexthopsocklen = 0;
94
directly_connected = -1;
95
targetipstring[0] = '\0';
96
sourceipstring[0] = '\0';
97
nameIPBuf = NULL;
98
memset(&MACaddress, 0, sizeof(MACaddress));
99
memset(&SrcMACaddress, 0, sizeof(SrcMACaddress));
100
memset(&NextHopMACaddress, 0, sizeof(NextHopMACaddress));
101
MACaddress_set = SrcMACaddress_set = NextHopMACaddress_set = false;
102
htn.msecs_used = 0;
103
htn.toclock_running = false;
104
htn.host_start = htn.host_end = 0;
105
interface_type = devt_other;
106
devname[0] = '\0';
107
devfullname[0] = '\0';
108
mtu = 0;
109
state_reason_init(&reason);
110
memset(&pingprobe, 0, sizeof(pingprobe));
111
pingprobe_state = PORT_UNKNOWN;
112
}
113
114
115
const char * Target::deviceName() const {
116
return (devname[0] != '\0')? devname : NULL;
117
}
118
119
const char * Target::deviceFullName() const {
120
return (devfullname[0] != '\0')? devfullname : NULL;
121
}
122
123
Target::~Target() {
124
FreeInternal();
125
#ifndef NOLUA
126
for (ScriptResults::iterator it = scriptResults.begin();
127
it != scriptResults.end(); it++) {
128
delete (*it);
129
}
130
#endif
131
}
132
133
void Target::FreeInternal() {
134
/* Free the DNS name if we resolved one */
135
if (hostname)
136
free(hostname);
137
138
if (targetname)
139
free(targetname);
140
141
if (nameIPBuf) {
142
free(nameIPBuf);
143
nameIPBuf = NULL;
144
}
145
146
if (FPR) delete FPR;
147
for (std::vector<EarlySvcResponse *>::iterator it=earlySvcResponses.begin();
148
it != earlySvcResponses.end(); it++) {
149
free(*it);
150
}
151
earlySvcResponses.clear();
152
}
153
154
/* Creates a "presentation" formatted string out of the IPv4/IPv6 address.
155
Called when the IP changes */
156
void Target::GenerateTargetIPString() {
157
struct sockaddr_in *sin = (struct sockaddr_in *) &targetsock;
158
#if HAVE_IPV6
159
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &targetsock;
160
#endif
161
162
if (inet_ntop(sin->sin_family, (sin->sin_family == AF_INET)?
163
(char *) &sin->sin_addr :
164
#if HAVE_IPV6
165
(char *) &sin6->sin6_addr,
166
#else
167
(char *) NULL,
168
#endif
169
targetipstring, sizeof(targetipstring)) == NULL) {
170
fatal("Failed to convert target address to presentation format!?! Error: %s", strerror(socket_errno()));
171
}
172
}
173
174
/* Creates a "presentation" formatted string out of the IPv4/IPv6 address.
175
Called when the IP changes */
176
void Target::GenerateSourceIPString() {
177
struct sockaddr_in *sin = (struct sockaddr_in *) &sourcesock;
178
#if HAVE_IPV6
179
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &sourcesock;
180
#endif
181
182
if (inet_ntop(sin->sin_family, (sin->sin_family == AF_INET)?
183
(char *) &sin->sin_addr :
184
#if HAVE_IPV6
185
(char *) &sin6->sin6_addr,
186
#else
187
(char *) NULL,
188
#endif
189
sourceipstring, sizeof(sourceipstring)) == NULL) {
190
fatal("Failed to convert source address to presentation format!?! Error: %s", strerror(socket_errno()));
191
}
192
}
193
194
/* Returns the address family of the destination address. */
195
int Target::af() const {
196
return targetsock.ss_family;
197
}
198
199
/* Fills a sockaddr_storage with the AF_INET or AF_INET6 address
200
information of the target. This is a preferred way to get the
201
address since it is portable for IPv6 hosts. Returns 0 for
202
success. ss_len must be provided. It is not examined, but is set
203
to the size of the sockaddr copied in. */
204
int Target::TargetSockAddr(struct sockaddr_storage *ss, size_t *ss_len) const {
205
assert(ss);
206
assert(ss_len);
207
if (targetsocklen <= 0)
208
return 1;
209
assert(targetsocklen <= sizeof(*ss));
210
memcpy(ss, &targetsock, targetsocklen);
211
*ss_len = targetsocklen;
212
return 0;
213
}
214
215
const struct sockaddr_storage *Target::TargetSockAddr() const {
216
return &targetsock;
217
}
218
219
/* Note that it is OK to pass in a sockaddr_in or sockaddr_in6 casted
220
to sockaddr_storage */
221
void Target::setTargetSockAddr(const struct sockaddr_storage *ss, size_t ss_len) {
222
223
assert(ss_len > 0 && ss_len <= sizeof(*ss));
224
if (targetsocklen > 0) {
225
/* We had an old target sock, so we better blow away the hostname as
226
this one may be new. */
227
setHostName(NULL);
228
setTargetName(NULL);
229
}
230
memcpy(&targetsock, ss, ss_len);
231
targetsocklen = ss_len;
232
GenerateTargetIPString();
233
/* The ports array needs to know a name too */
234
ports.setIdStr(targetipstr());
235
}
236
237
// Returns IPv4 host address or {0} if unavailable.
238
struct in_addr Target::v4host() const {
239
const struct in_addr *addy = v4hostip();
240
struct in_addr in;
241
if (addy) return *addy;
242
in.s_addr = 0;
243
return in;
244
}
245
246
// Returns IPv4 host address or NULL if unavailable.
247
const struct in_addr *Target::v4hostip() const {
248
struct sockaddr_in *sin = (struct sockaddr_in *) &targetsock;
249
if (sin->sin_family == AF_INET) {
250
return &(sin->sin_addr);
251
}
252
return NULL;
253
}
254
255
const struct in6_addr *Target::v6hostip() const {
256
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &targetsock;
257
if (sin6->sin6_family == AF_INET6) {
258
return &(sin6->sin6_addr);
259
}
260
return NULL;
261
}
262
263
/* The source address used to reach the target */
264
int Target::SourceSockAddr(struct sockaddr_storage *ss, size_t *ss_len) const {
265
if (sourcesocklen <= 0)
266
return 1;
267
assert(sourcesocklen <= sizeof(*ss));
268
if (ss)
269
memcpy(ss, &sourcesock, sourcesocklen);
270
if (ss_len)
271
*ss_len = sourcesocklen;
272
return 0;
273
}
274
275
const struct sockaddr_storage *Target::SourceSockAddr() const {
276
return &sourcesock;
277
}
278
279
/* Note that it is OK to pass in a sockaddr_in or sockaddr_in6 casted
280
to sockaddr_storage */
281
void Target::setSourceSockAddr(const struct sockaddr_storage *ss, size_t ss_len) {
282
assert(ss_len > 0 && ss_len <= sizeof(*ss));
283
memcpy(&sourcesock, ss, ss_len);
284
sourcesocklen = ss_len;
285
GenerateSourceIPString();
286
}
287
288
// Returns IPv4 host address or {0} if unavailable.
289
struct sockaddr_storage Target::source() const {
290
return sourcesock;
291
}
292
293
// Returns IPv4 host address or NULL if unavailable.
294
const struct in_addr *Target::v4sourceip() const {
295
struct sockaddr_in *sin = (struct sockaddr_in *) &sourcesock;
296
if (sin->sin_family == AF_INET) {
297
return &(sin->sin_addr);
298
}
299
return NULL;
300
}
301
302
// Returns IPv6 host address or NULL if unavailable.
303
const struct in6_addr *Target::v6sourceip() const {
304
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &sourcesock;
305
if (sin6->sin6_family == AF_INET6) {
306
return &(sin6->sin6_addr);
307
}
308
return NULL;
309
}
310
311
/* You can set to NULL to erase a name or if it failed to resolve -- or
312
just don't call this if it fails to resolve */
313
void Target::setHostName(const char *name) {
314
char *p;
315
if (hostname) {
316
free(hostname);
317
hostname = NULL;
318
}
319
if (name) {
320
p = hostname = strdup(name);
321
while (*p) {
322
// I think only a-z A-Z 0-9 . and - are allowed, but I'll be a little more
323
// generous.
324
if (!isalnum((int) (unsigned char) *p) && !strchr(".-+=:_~*", *p)) {
325
log_write(LOG_STDOUT, "Illegal character(s) in hostname -- replacing with '*'\n");
326
*p = '*';
327
}
328
p++;
329
}
330
}
331
}
332
333
void Target::setTargetName(const char *name) {
334
if (targetname) {
335
free(targetname);
336
targetname = NULL;
337
}
338
if (name) {
339
targetname = strdup(name);
340
}
341
}
342
343
/* Generates a printable string consisting of the host's IP
344
address and hostname (if available). Eg "www.insecure.org
345
(64.71.184.53)" or "fe80::202:e3ff:fe14:1102". The name is
346
written into the buffer provided, which is also returned. Results
347
that do not fit in buflen will be truncated. */
348
const char *Target::NameIP(char *buf, size_t buflen) const {
349
assert(buf);
350
assert(buflen > 8);
351
if (targetname)
352
Snprintf(buf, buflen, "%s (%s)", targetname, targetipstring);
353
else if (hostname)
354
Snprintf(buf, buflen, "%s (%s)", hostname, targetipstring);
355
else
356
Strncpy(buf, targetipstring, buflen);
357
return buf;
358
}
359
360
/* This next version returns a static buffer -- so no concurrency */
361
const char *Target::NameIP() const {
362
/* Add 3 characters for the hostname and IP string, hence we allocate
363
(FQDN_LEN + INET6_ADDRSTRLEN + 4) octets, with octet for the null terminator */
364
if (!nameIPBuf) nameIPBuf = (char *) safe_malloc(FQDN_LEN + INET6_ADDRSTRLEN + 4);
365
return NameIP(nameIPBuf, FQDN_LEN + INET6_ADDRSTRLEN + 4);
366
}
367
368
/* Returns the next hop for sending packets to this host. Returns true if
369
next_hop was filled in. It might be false, for example, if
370
next_hop has never been set */
371
bool Target::nextHop(struct sockaddr_storage *next_hop, size_t *next_hop_len) const {
372
if (nexthopsocklen <= 0)
373
return false;
374
assert(nexthopsocklen <= sizeof(*next_hop));
375
if (next_hop)
376
memcpy(next_hop, &nexthopsock, nexthopsocklen);
377
if (next_hop_len)
378
*next_hop_len = nexthopsocklen;
379
return true;
380
}
381
382
/* If the host is directly connected on a network, set and retrieve
383
that information here. directlyConnected() will abort if it hasn't
384
been set yet. */
385
void Target::setDirectlyConnected(bool connected) {
386
directly_connected = connected? 1 : 0;
387
}
388
389
int Target::directlyConnectedOrUnset() const {
390
return directly_connected;
391
}
392
393
bool Target::directlyConnected() const {
394
assert(directly_connected == 0 || directly_connected == 1);
395
return directly_connected;
396
}
397
398
/* Note that it is OK to pass in a sockaddr_in or sockaddr_in6 casted
399
to sockaddr_storage */
400
void Target::setNextHop(const struct sockaddr_storage *next_hop, size_t next_hop_len) {
401
assert(next_hop_len > 0 && next_hop_len <= sizeof(nexthopsock));
402
memcpy(&nexthopsock, next_hop, next_hop_len);
403
nexthopsocklen = next_hop_len;
404
}
405
406
/* Set MTU (to correspond with devname) */
407
void Target::setMTU(int devmtu) {
408
mtu = devmtu;
409
}
410
411
/* Get MTU (to correspond with devname) */
412
int Target::MTU(void) const {
413
return mtu;
414
}
415
416
/* Starts the timeout clock for the host running (e.g. you are
417
beginning a scan). If you do not have the current time handy,
418
you can pass in NULL. When done, call stopTimeOutClock (it will
419
also automatically be stopped of timedOut() returns true) */
420
void Target::startTimeOutClock(const struct timeval *now) {
421
assert(htn.toclock_running == false);
422
htn.toclock_running = true;
423
if (now) htn.toclock_start = *now;
424
else gettimeofday(&htn.toclock_start, NULL);
425
if (!htn.host_start) htn.host_start = htn.toclock_start.tv_sec;
426
}
427
/* The complement to startTimeOutClock. */
428
void Target::stopTimeOutClock(const struct timeval *now) {
429
struct timeval tv;
430
assert(htn.toclock_running == true);
431
htn.toclock_running = false;
432
if (now) tv = *now;
433
else gettimeofday(&tv, NULL);
434
htn.msecs_used += TIMEVAL_MSEC_SUBTRACT(tv, htn.toclock_start);
435
htn.host_end = tv.tv_sec;
436
}
437
/* Returns whether the host is timedout. If the timeoutclock is
438
running, counts elapsed time for that. Pass NULL if you don't have the
439
current time handy. You might as well also pass NULL if the
440
clock is not running, as the func won't need the time. */
441
bool Target::timedOut(const struct timeval *now) const {
442
unsigned long used = htn.msecs_used;
443
struct timeval tv;
444
445
if (!o.host_timeout) return false;
446
if (htn.toclock_running) {
447
if (now) tv = *now;
448
else gettimeofday(&tv, NULL);
449
used += TIMEVAL_MSEC_SUBTRACT(tv, htn.toclock_start);
450
}
451
452
return (used > o.host_timeout);
453
}
454
455
456
/* Returns zero if MAC address set successfully */
457
int Target::setMACAddress(const u8 *addy) {
458
if (!addy) return 1;
459
memcpy(MACaddress, addy, 6);
460
MACaddress_set = 1;
461
return 0;
462
}
463
464
int Target::setSrcMACAddress(const u8 *addy) {
465
if (!addy) return 1;
466
memcpy(SrcMACaddress, addy, 6);
467
SrcMACaddress_set = 1;
468
return 0;
469
}
470
471
int Target::setNextHopMACAddress(const u8 *addy) {
472
if (!addy) return 1;
473
memcpy(NextHopMACaddress, addy, 6);
474
NextHopMACaddress_set = 1;
475
return 0;
476
}
477
478
/* Set the device names so that they can be returned by deviceName()
479
and deviceFullName(). The normal name may not include alias
480
qualifier, while the full name may include it (e.g. "eth1:1"). If
481
these are non-null, they will overwrite the stored version */
482
void Target::setDeviceNames(const char *name, const char *fullname) {
483
if (name) Strncpy(devname, name, sizeof(devname));
484
if (fullname) Strncpy(devfullname, fullname, sizeof(devfullname));
485
}
486
487
/* Returns the 6-byte long MAC address, or NULL if none has been set */
488
const u8 *Target::MACAddress() const {
489
return (MACaddress_set)? MACaddress : NULL;
490
}
491
492
const u8 *Target::SrcMACAddress() const {
493
return (SrcMACaddress_set)? SrcMACaddress : NULL;
494
}
495
496
const u8 *Target::NextHopMACAddress() const {
497
return (NextHopMACaddress_set)? NextHopMACaddress : NULL;
498
}
499
500
int Target::osscanPerformed(void) const {
501
return osscan_flag;
502
}
503
504
void Target::osscanSetFlag(int flag) {
505
if(osscan_flag == OS_PERF_UNREL)
506
return;
507
else
508
osscan_flag = flag;
509
}
510
511