mirror of
https://github.com/nmap/nmap.git
synced 2025-12-09 22:21:29 +00:00
Add -ip-options support
This commit is contained in:
@@ -4,6 +4,14 @@
|
||||
o Worked with Zhao to improve the new OS detection system with
|
||||
better algorithms, some probe changes, and some bug fixes.
|
||||
|
||||
o Nmap now supports IP options with the new --ip-options flag. You
|
||||
can specify any optiosn in hex, or use "R" (record route), "T"
|
||||
(record timestamp), "U") (record route & timestamp), "S [route]"
|
||||
(strict source route), or "L [route]" (loose source route). Specify
|
||||
--packet-trace to display IP options of responses. For further
|
||||
information and examples, see http://insecure.org/nmap/man/ and
|
||||
http://seclists.org/nmap-dev/2006/q3/0052.html .
|
||||
|
||||
o Nmap now uses the (relatively) new libpcap pcap_get_selectable_fd
|
||||
API on systems which support it. This means that we no longer need
|
||||
to hack the included Pcap to better support Linux. So Nmap will now
|
||||
|
||||
10
NmapOps.cc
10
NmapOps.cc
@@ -252,6 +252,10 @@ void NmapOps::Initialize() {
|
||||
dns_servers = NULL;
|
||||
noninteractive = false;
|
||||
current_scantype = STYPE_UNKNOWN;
|
||||
ipoptions = NULL;
|
||||
ipoptionslen = 0;
|
||||
ipopt_firsthop = 0;
|
||||
ipopt_lasthop = 0;
|
||||
release_memory = false;
|
||||
|
||||
}
|
||||
@@ -446,6 +450,12 @@ void NmapOps::ValidateOptions() {
|
||||
if (min_parallelism > max_parallelism)
|
||||
max_parallelism = min_parallelism;
|
||||
|
||||
if(o.ipoptionslen && ! o.isr00t)
|
||||
fatal("To use ip options you must be root.");
|
||||
|
||||
if(o.ipoptions && o.osscan)
|
||||
error("WARNING: Ip options are NOT used while OS scanning!");
|
||||
|
||||
}
|
||||
|
||||
void NmapOps::setMaxRttTimeout(int rtt)
|
||||
|
||||
@@ -293,6 +293,13 @@ class NmapOps {
|
||||
char *dns_servers;
|
||||
bool log_errors;
|
||||
|
||||
/* ip options used in build_*_raw() */
|
||||
u8 *ipoptions;
|
||||
int ipoptionslen;
|
||||
int ipopt_firsthop; // offset in ipoptions where is first hop for source/strict routing
|
||||
int ipopt_lasthop; // offset in ipoptions where is space for targets ip for source/strict routing
|
||||
|
||||
|
||||
// Statistics Options set in nmap.cc
|
||||
int numhosts_scanned;
|
||||
int numhosts_up;
|
||||
|
||||
49
idle_scan.cc
49
idle_scan.cc
@@ -186,12 +186,14 @@ static int ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent,
|
||||
gettimeofday(&tv_sent[tries], NULL);
|
||||
|
||||
/* Time to send the pr0be!*/
|
||||
send_tcp_raw(proxy->rawsd, proxy->ethptr, proxy->host.v4sourceip(),
|
||||
proxy->host.v4hostip(), o.ttl, false, base_port + tries,
|
||||
proxy->probe_port,
|
||||
seq_base + (packet_send_count++ * 500) + 1, ack, 0,
|
||||
TH_SYN|TH_ACK, 0, 0,
|
||||
(u8 *) "\x02\x04\x05\xb4", 4, NULL, 0);
|
||||
send_tcp_raw(proxy->rawsd, proxy->ethptr,
|
||||
proxy->host.v4sourceip(), proxy->host.v4hostip(),
|
||||
o.ttl, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
base_port + tries, proxy->probe_port,
|
||||
seq_base + (packet_send_count++ * 500) + 1, ack, 0, TH_SYN|TH_ACK, 0, 0,
|
||||
(u8 *) "\x02\x04\x05\xb4", 4,
|
||||
NULL, 0);
|
||||
sent++;
|
||||
tries++;
|
||||
|
||||
@@ -416,11 +418,14 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
|
||||
a response with the exact request for timing purposes. So I
|
||||
think I'll use TH_SYN, although it is a tough call. */
|
||||
/* We can't use decoys 'cause that would screw up the IPIDs */
|
||||
send_tcp_raw(proxy->rawsd, proxy->ethptr, proxy->host.v4sourceip(),
|
||||
proxy->host.v4hostip(), o.ttl, false,
|
||||
send_tcp_raw(proxy->rawsd, proxy->ethptr,
|
||||
proxy->host.v4sourceip(), proxy->host.v4hostip(),
|
||||
o.ttl, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
o.magic_port + probes_sent + 1, proxy->probe_port,
|
||||
sequence_base + probes_sent + 1, ack, 0, TH_SYN|TH_ACK,
|
||||
0, 0, (u8 *) "\x02\x04\x05\xb4", 4, NULL, 0);
|
||||
sequence_base + probes_sent + 1, ack, 0, TH_SYN|TH_ACK, 0, 0,
|
||||
(u8 *) "\x02\x04\x05\xb4",4,
|
||||
NULL, 0);
|
||||
gettimeofday(&probe_send_times[probes_sent], NULL);
|
||||
probes_sent++;
|
||||
|
||||
@@ -523,11 +528,14 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
|
||||
if (first_target) {
|
||||
for (probes_sent = 0; probes_sent < 4; probes_sent++) {
|
||||
if (probes_sent) usleep(50000);
|
||||
send_tcp_raw(proxy->rawsd, proxy->ethptr, first_target,
|
||||
proxy->host.v4hostip(),
|
||||
o.ttl, false,o.magic_port, proxy->probe_port,
|
||||
sequence_base + probes_sent + 1, ack, 0, TH_SYN|TH_ACK,
|
||||
0, 0, (u8 *) "\x02\x04\x05\xb4", 4, NULL, 0);
|
||||
send_tcp_raw(proxy->rawsd, proxy->ethptr,
|
||||
first_target, proxy->host.v4hostip(),
|
||||
o.ttl, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
o.magic_port, proxy->probe_port,
|
||||
sequence_base + probes_sent + 1, ack, 0, TH_SYN|TH_ACK, 0, 0,
|
||||
(u8 *) "\x02\x04\x05\xb4",
|
||||
4, NULL, 0);
|
||||
|
||||
}
|
||||
|
||||
@@ -680,10 +688,13 @@ static int idlescan_countopen2(struct idle_proxy_info *proxy,
|
||||
but doing it the straightforward way (using the same decoys as
|
||||
we use in probing the proxy box is risky. I'll have to think
|
||||
about this more. */
|
||||
send_tcp_raw(proxy->rawsd, eth.ethsd? ð : NULL, proxy->host.v4hostip(),
|
||||
target->v4hostip(),
|
||||
o.ttl, false, proxy->probe_port, ports[pr0be], seq, 0, 0, TH_SYN, 0, 0,
|
||||
(u8 *) "\x02\x04\x05\xb4", 4, o.extra_payload, o.extra_payload_length);
|
||||
send_tcp_raw(proxy->rawsd, eth.ethsd? ð : NULL,
|
||||
proxy->host.v4hostip(), target->v4hostip(),
|
||||
o.ttl, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
proxy->probe_port, ports[pr0be], seq, 0, 0, TH_SYN, 0, 0,
|
||||
(u8 *) "\x02\x04\x05\xb4", 4,
|
||||
o.extra_payload, o.extra_payload_length);
|
||||
}
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
|
||||
20
nmap.cc
20
nmap.cc
@@ -257,6 +257,7 @@ printf("%s %s ( %s )\n"
|
||||
" -e <iface>: Use specified interface\n"
|
||||
" -g/--source-port <portnum>: Use given port number\n"
|
||||
" --data-length <num>: Append random data to sent packets\n"
|
||||
" --ip-options <options>: Send packets with specified ip options\n"
|
||||
" --ttl <val>: Set IP time-to-live field\n"
|
||||
" --spoof-mac <mac address/prefix/vendor name>: Spoof your MAC address\n"
|
||||
" --badsum: Send packets with a bogus TCP/UDP checksum\n"
|
||||
@@ -583,6 +584,8 @@ int nmap_main(int argc, char *argv[]) {
|
||||
{"log-errors", no_argument, 0, 0},
|
||||
{"dns_servers", required_argument, 0, 0},
|
||||
{"dns-servers", required_argument, 0, 0},
|
||||
{"ip_options", required_argument, 0, 0},
|
||||
{"ip-options", required_argument, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -792,6 +795,13 @@ int nmap_main(int argc, char *argv[]) {
|
||||
o.fragscan = atoi(optarg);
|
||||
if (o.fragscan <= 0 || o.fragscan % 8 != 0)
|
||||
fatal("Data payload MTU must be >0 and multiple of 8");
|
||||
} else if (strcmp(long_options[option_index].name, "ip-options") == 0){
|
||||
o.ipoptions = (u8*) safe_malloc(4*10+1);
|
||||
o.ipoptionslen = parse_ip_options(optarg, o.ipoptions, 4*10+1, &o.ipopt_firsthop, &o.ipopt_lasthop);
|
||||
if(o.ipoptionslen > 4*10)
|
||||
fatal("Ip options can't be more than 40 bytes long");
|
||||
if(o.ipoptionslen %4 != 0)
|
||||
fatal("Ip options must be multiple of 4 (read length is %i bytes)", o.ipoptionslen);
|
||||
} else {
|
||||
fatal("Unknown long option (%s) given@#!$#$", long_options[option_index].name);
|
||||
}
|
||||
@@ -1102,6 +1112,16 @@ int nmap_main(int argc, char *argv[]) {
|
||||
|
||||
o.ValidateOptions();
|
||||
|
||||
// print ip options
|
||||
if((o.debugging || o.packetTrace()) && o.ipoptionslen){
|
||||
char buf[256]; // 256 > 5*40
|
||||
bintohexstr(buf, sizeof(buf), (char*)o.ipoptions, o.ipoptionslen);
|
||||
if(o.ipoptionslen>=8) // at least one ip address
|
||||
log_write(LOG_STDOUT, "Binary ip options to be send:\n%s", buf);
|
||||
log_write(LOG_STDOUT, "Parsed ip options to be send:\n%s\n",
|
||||
print_ip_options(o.ipoptions, o.ipoptionslen));
|
||||
}
|
||||
|
||||
/* Open the log files, now that we know whether the user wants them appended
|
||||
or overwritten */
|
||||
if (normalfilename)
|
||||
|
||||
16
osscan.cc
16
osscan.cc
@@ -613,7 +613,7 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
|
||||
/* Test 1 */
|
||||
if (!FPtests[1]) {
|
||||
if (o.scan_delay) enforce_scan_delay(NULL);
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
current_port, openport, sequence_base, 0, 0,
|
||||
TH_ECE|TH_SYN, 0, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000", 20, NULL, 0);
|
||||
}
|
||||
@@ -621,7 +621,7 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
|
||||
/* Test 2 */
|
||||
if (!FPtests[2]) {
|
||||
if (o.scan_delay) enforce_scan_delay(NULL);
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
current_port +1, openport, sequence_base, 0, 0,
|
||||
0, 0, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
|
||||
}
|
||||
@@ -629,7 +629,7 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
|
||||
/* Test 3 */
|
||||
if (!FPtests[3]) {
|
||||
if (o.scan_delay) enforce_scan_delay(NULL);
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
current_port +2, openport, sequence_base, 0, 0,
|
||||
TH_SYN|TH_FIN|TH_URG|TH_PUSH, 0, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
|
||||
}
|
||||
@@ -637,7 +637,7 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
|
||||
/* Test 4 */
|
||||
if (!FPtests[4]) {
|
||||
if (o.scan_delay) enforce_scan_delay(NULL);
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
current_port +3, openport, sequence_base, 0, 0,
|
||||
TH_ACK, 0, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
|
||||
}
|
||||
@@ -646,7 +646,7 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
|
||||
/* Test 5 */
|
||||
if (!FPtests[5]) {
|
||||
if (o.scan_delay) enforce_scan_delay(NULL);
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
current_port +4, closedport, sequence_base, 0, 0,
|
||||
TH_SYN, 0, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
|
||||
}
|
||||
@@ -654,7 +654,7 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
|
||||
/* Test 6 */
|
||||
if (!FPtests[6]) {
|
||||
if (o.scan_delay) enforce_scan_delay(NULL);
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
current_port +5, closedport, sequence_base, 0, 0,
|
||||
TH_ACK, 0, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
|
||||
}
|
||||
@@ -662,7 +662,7 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
|
||||
/* Test 7 */
|
||||
if (!FPtests[7]) {
|
||||
if (o.scan_delay) enforce_scan_delay(NULL);
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
current_port +6, closedport, sequence_base, 0, 0,
|
||||
TH_FIN|TH_PUSH|TH_URG, 0, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0);
|
||||
}
|
||||
@@ -749,7 +749,7 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
|
||||
usleep(remaining_us);
|
||||
}
|
||||
}
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
o.magic_port + seq_packets_sent + 1,
|
||||
openport,
|
||||
sequence_base + seq_packets_sent + 1, 0, 0,
|
||||
|
||||
39
osscan2.cc
39
osscan2.cc
@@ -1277,7 +1277,7 @@ void HostOsScan::sendTSeqProbe(HostOsScanStats *hss, int probeNo) {
|
||||
|
||||
if(hss->openTCPPort == -1) return;
|
||||
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
tcpPortBase + probeNo, hss->openTCPPort,
|
||||
tcpSeqBase + probeNo, tcpAck, 0,
|
||||
TH_SYN, prbWindowSz[probeNo], 0, prbOpts[probeNo].val, prbOpts[probeNo].len,
|
||||
@@ -1292,7 +1292,7 @@ void HostOsScan::sendTOpsProbe(HostOsScanStats *hss, int probeNo) {
|
||||
|
||||
if(hss->openTCPPort == -1) return;
|
||||
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
tcpPortBase + NUM_SEQ_SAMPLES + probeNo,
|
||||
hss->openTCPPort, tcpSeqBase, tcpAck, 0, TH_SYN,
|
||||
prbWindowSz[probeNo], 0, prbOpts[probeNo].val,
|
||||
@@ -1304,7 +1304,7 @@ void HostOsScan::sendTEcnProbe(HostOsScanStats *hss) {
|
||||
|
||||
if(hss->openTCPPort == -1) return;
|
||||
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
tcpPortBase + NUM_SEQ_SAMPLES + 6, hss->openTCPPort,
|
||||
tcpSeqBase, 0, 8, TH_CWR|TH_ECE|TH_SYN, prbWindowSz[6],
|
||||
63477, prbOpts[6].val, prbOpts[6].len, NULL, 0);
|
||||
@@ -1319,51 +1319,52 @@ void HostOsScan::sendT1_7Probe(HostOsScanStats *hss, int probeNo) {
|
||||
switch(probeNo) {
|
||||
case 0: /* T1 */
|
||||
if(hss->openTCPPort == -1) return;
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
port_base, hss->openTCPPort, tcpSeqBase, tcpAck, 0,
|
||||
TH_SYN, prbWindowSz[0], 0, prbOpts[0].val,
|
||||
prbOpts[0].len, NULL, 0);
|
||||
break;
|
||||
case 1: /* T2 */
|
||||
if(hss->openTCPPort == -1) return;
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, true,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, true, NULL, 0,
|
||||
port_base + 1, hss->openTCPPort, tcpSeqBase, tcpAck, 0,
|
||||
0, prbWindowSz[7], 0, prbOpts[7].val, prbOpts[7].len, NULL, 0);
|
||||
0, prbWindowSz[7], 0, prbOpts[7].val,
|
||||
prbOpts[7].len, NULL, 0);
|
||||
break;
|
||||
case 2: /* T3 */
|
||||
if(hss->openTCPPort == -1) return;
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
port_base + 2, hss->openTCPPort, tcpSeqBase, tcpAck, 0,
|
||||
TH_SYN|TH_FIN|TH_URG|TH_PUSH, prbWindowSz[8], 0,
|
||||
prbOpts[8].val, prbOpts[8].len, NULL, 0);
|
||||
TH_SYN|TH_FIN|TH_URG|TH_PUSH, prbWindowSz[8], 0, prbOpts[8].val,
|
||||
prbOpts[8].len, NULL, 0);
|
||||
break;
|
||||
case 3: /* T4 */
|
||||
if(hss->openTCPPort == -1) return;
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, true,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, true, NULL, 0,
|
||||
port_base + 3, hss->openTCPPort, tcpSeqBase, tcpAck, 0,
|
||||
TH_ACK, prbWindowSz[9], 0, prbOpts[9].val,
|
||||
prbOpts[9].len, NULL, 0);
|
||||
break;
|
||||
case 4: /* T5 */
|
||||
if(hss->closedTCPPort == -1) return;
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
port_base + 4, hss->closedTCPPort, tcpSeqBase, tcpAck,
|
||||
0, TH_SYN, prbWindowSz[10], 0, prbOpts[10].val,
|
||||
prbOpts[10].len, NULL, 0);
|
||||
break;
|
||||
case 5: /* T6 */
|
||||
if(hss->closedTCPPort == -1) return;
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, true,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, true, NULL, 0,
|
||||
port_base + 5, hss->closedTCPPort, tcpSeqBase, tcpAck,
|
||||
0, TH_ACK, prbWindowSz[11], 0, prbOpts[11].val,
|
||||
prbOpts[11].len, NULL, 0);
|
||||
break;
|
||||
case 6: /* T7 */
|
||||
if(hss->closedTCPPort == -1) return;
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
|
||||
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false, NULL, 0,
|
||||
port_base + 6, hss->closedTCPPort, tcpSeqBase, tcpAck,
|
||||
0, TH_FIN|TH_PUSH|TH_URG, prbWindowSz[12], 0,
|
||||
prbOpts[12].val, prbOpts[12].len, NULL, 0);
|
||||
0, TH_FIN|TH_PUSH|TH_URG, prbWindowSz[12], 0, prbOpts[12].val,
|
||||
prbOpts[12].len, NULL, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2962,9 +2963,11 @@ int send_icmp_echo_probe(int sd, struct eth_nfo *eth,
|
||||
int res = -1;
|
||||
|
||||
for(decoy = 0; decoy < o.numdecoys; decoy++) {
|
||||
packet = build_icmp_raw(&o.decoys[decoy], victim, o.ttl,
|
||||
get_random_u16(), tos, df, seq, id, ICMP_ECHO, pcode, NULL,
|
||||
datalen, &packetlen);
|
||||
packet = build_icmp_raw(&o.decoys[decoy], victim,
|
||||
o.ttl, get_random_u16(), tos, df,
|
||||
NULL, 0,
|
||||
seq, id, ICMP_ECHO, pcode,
|
||||
NULL, datalen, &packetlen);
|
||||
if(!packet) return -1;
|
||||
res = send_ip_packet(sd, eth, packet, packetlen);
|
||||
free(packet);
|
||||
|
||||
@@ -2134,9 +2134,12 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
|
||||
}
|
||||
|
||||
for(decoy = 0; decoy < o.numdecoys; decoy++) {
|
||||
packet = build_tcp_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl, false,
|
||||
ipid, sport, pspec->pd.tcp.dport, seq, ack, 0,
|
||||
pspec->pd.tcp.flags, 0, 0, tcpops, tcpopslen,
|
||||
packet = build_tcp_raw(&o.decoys[decoy], hss->target->v4hostip(),
|
||||
o.ttl, ipid, IP_TOS_DEFAULT, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
sport, pspec->pd.tcp.dport,
|
||||
seq, ack, 0, pspec->pd.tcp.flags, 0, 0,
|
||||
tcpops, tcpopslen,
|
||||
o.extra_payload, o.extra_payload_length,
|
||||
&packetlen);
|
||||
if (decoy == o.decoyturn) {
|
||||
@@ -2148,8 +2151,10 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
|
||||
}
|
||||
} else if (USI->udp_scan) {
|
||||
for(decoy = 0; decoy < o.numdecoys; decoy++) {
|
||||
packet = build_udp_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl,
|
||||
sport, pspec->pd.udp.dport, ipid,
|
||||
packet = build_udp_raw(&o.decoys[decoy], hss->target->v4hostip(),
|
||||
o.ttl, ipid, IP_TOS_DEFAULT, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
sport, pspec->pd.udp.dport,
|
||||
o.extra_payload, o.extra_payload_length,
|
||||
&packetlen);
|
||||
if (decoy == o.decoyturn) {
|
||||
@@ -2164,27 +2169,37 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
|
||||
switch(pspec->proto) {
|
||||
|
||||
case IPPROTO_TCP:
|
||||
packet = build_tcp_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl, false,
|
||||
ipid, sport, o.magic_port, get_random_u32(),
|
||||
get_random_u32(), 0, TH_ACK, 0, 0, NULL,
|
||||
0, o.extra_payload, o.extra_payload_length,
|
||||
packet = build_tcp_raw(&o.decoys[decoy], hss->target->v4hostip(),
|
||||
o.ttl, ipid, IP_TOS_DEFAULT, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
sport, o.magic_port,
|
||||
get_random_u32(), get_random_u32(), 0, TH_ACK, 0, 0,
|
||||
NULL,0,
|
||||
o.extra_payload, o.extra_payload_length,
|
||||
&packetlen);
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
packet = build_icmp_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl,
|
||||
ipid, 0, false, 0, 0, 8, 0, o.extra_payload,
|
||||
o.extra_payload_length, &packetlen);
|
||||
packet = build_icmp_raw(&o.decoys[decoy], hss->target->v4hostip(),
|
||||
o.ttl, ipid, IP_TOS_DEFAULT, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
0, 0, 8, 0,
|
||||
o.extra_payload, o.extra_payload_length,
|
||||
&packetlen);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
packet = build_udp_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl,
|
||||
sport, o.magic_port, ipid,
|
||||
packet = build_udp_raw(&o.decoys[decoy], hss->target->v4hostip(),
|
||||
o.ttl, ipid, IP_TOS_DEFAULT, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
sport, o.magic_port,
|
||||
o.extra_payload, o.extra_payload_length,
|
||||
&packetlen);
|
||||
|
||||
break;
|
||||
default:
|
||||
packet = build_ip_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl,
|
||||
pspec->proto, ipid, 0, false,
|
||||
packet = build_ip_raw(&o.decoys[decoy], hss->target->v4hostip(),
|
||||
pspec->proto,
|
||||
o.ttl, ipid, IP_TOS_DEFAULT, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
o.extra_payload, o.extra_payload_length,
|
||||
&packetlen);
|
||||
break;
|
||||
@@ -2767,6 +2782,8 @@ static bool get_arp_result(UltraScanInfo *USI, struct timeval *stime) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Tries to get one *good* (finishes a probe) pcap response by the
|
||||
(absolute) time given in stime. Even if stime is now, try an
|
||||
ultra-quick pcap read just in case. Returns true if a "good" result
|
||||
|
||||
30
targets.cc
30
targets.cc
@@ -900,7 +900,11 @@ else {
|
||||
|
||||
o.decoys[o.decoyturn].s_addr = target->v4source().s_addr;
|
||||
|
||||
send_udp_raw_decoys( rawsd, eth, target->v4hostip(), o.ttl, sportbase + trynum, probe_port, seq, o.extra_payload, o.extra_payload_length);
|
||||
send_udp_raw_decoys( rawsd, eth, target->v4hostip(),
|
||||
o.ttl, seq,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
sportbase + trynum, probe_port,
|
||||
o.extra_payload, o.extra_payload_length);
|
||||
|
||||
|
||||
return 0;
|
||||
@@ -924,11 +928,21 @@ else {
|
||||
o.decoys[o.decoyturn].s_addr = target->v4source().s_addr;
|
||||
|
||||
if (pingtype & PINGTYPE_TCP_USE_SYN) {
|
||||
send_tcp_raw_decoys( rawsd, eth, target->v4hostip(), o.ttl, false, sportbase + trynum, probe_port, myseq, myack, 0, TH_SYN, 0, 0, (u8 *) "\x02\x04\x05\xb4", 4, o.extra_payload,
|
||||
o.extra_payload_length);
|
||||
send_tcp_raw_decoys( rawsd, eth, target->v4hostip(),
|
||||
o.ttl, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
sportbase + trynum, probe_port,
|
||||
myseq, myack, 0, TH_SYN, 0, 0,
|
||||
(u8 *) "\x02\x04\x05\xb4", 4,
|
||||
o.extra_payload, o.extra_payload_length);
|
||||
} else {
|
||||
send_tcp_raw_decoys( rawsd, eth, target->v4hostip(), o.ttl, false, sportbase + trynum, probe_port, myseq, myack, 0, TH_ACK, 0, 0, NULL, 0, o.extra_payload,
|
||||
o.extra_payload_length);
|
||||
send_tcp_raw_decoys( rawsd, eth, target->v4hostip(),
|
||||
o.ttl, false,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
sportbase + trynum, probe_port,
|
||||
myseq, myack, 0, TH_ACK, 0, 0,
|
||||
NULL, 0,
|
||||
o.extra_payload, o.extra_payload_length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1068,7 +1082,11 @@ if (ptech.icmpscan) {
|
||||
fprintf(stderr, "sendto: %s\n", strerror(sock_err));
|
||||
}
|
||||
} else {
|
||||
send_ip_raw( rawsd, ethptr, &o.decoys[decoy], target->v4hostip(), o.ttl, IPPROTO_ICMP, ping, icmplen);
|
||||
send_ip_raw(rawsd, ethptr,
|
||||
&o.decoys[decoy], target->v4hostip(),
|
||||
IPPROTO_ICMP, o.ttl,
|
||||
o.ipoptions, o.ipoptionslen,
|
||||
ping, icmplen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
339
tcpip.cc
339
tcpip.cc
@@ -409,7 +409,7 @@ static const char *ippackethdrinfo(const u8 *packet, u32 len) {
|
||||
struct ip *ip = (struct ip *) packet;
|
||||
struct tcphdr *tcp;
|
||||
udphdr_bsd *udp;
|
||||
char ipinfo[64];
|
||||
char ipinfo[512];
|
||||
char srchost[INET6_ADDRSTRLEN], dsthost[INET6_ADDRSTRLEN];
|
||||
char *p;
|
||||
struct in_addr saddr, daddr;
|
||||
@@ -434,8 +434,11 @@ static const char *ippackethdrinfo(const u8 *packet, u32 len) {
|
||||
}
|
||||
|
||||
|
||||
snprintf(ipinfo, sizeof(ipinfo), "ttl=%d id=%d iplen=%d%s",
|
||||
ip->ip_ttl, ntohs(ip->ip_id), ntohs(ip->ip_len), fragnfo);
|
||||
snprintf(ipinfo, sizeof(ipinfo), "ttl=%d id=%d iplen=%d%s %s%s%s",
|
||||
ip->ip_ttl, ntohs(ip->ip_id), ntohs(ip->ip_len), fragnfo,
|
||||
ip->ip_hl==5?"":"ipopts={",
|
||||
ip->ip_hl==5?"":print_ip_options((u8*)ip + sizeof(struct ip), MIN((ip->ip_hl-5)*4,len-sizeof(struct ip))),
|
||||
ip->ip_hl==5?"":"}");
|
||||
|
||||
if (ip->ip_p == IPPROTO_TCP) {
|
||||
char tflags[10];
|
||||
@@ -1012,18 +1015,69 @@ void eth_close_cached() {
|
||||
return;
|
||||
}
|
||||
|
||||
// fill ip header. no error check.
|
||||
// This function is also changing what's needed from host to network order.
|
||||
static inline int fill_ip_raw(
|
||||
struct ip *ip, int packetlen, u8* ipopt, int ipoptlen,
|
||||
int ip_tos, int ip_id, int ip_off, int ip_ttl, int ip_p,
|
||||
const struct in_addr *ip_src, const struct in_addr *ip_dst)
|
||||
{
|
||||
ip->ip_v = 4;
|
||||
ip->ip_hl = 5 + (ipoptlen/4);
|
||||
ip->ip_tos = ip_tos;
|
||||
ip->ip_len = htons(packetlen);
|
||||
ip->ip_id = htons(ip_id);
|
||||
ip->ip_off = htons(ip_off);
|
||||
ip->ip_ttl = ip_ttl;
|
||||
ip->ip_p = ip_p;
|
||||
ip->ip_src.s_addr = ip_src->s_addr;
|
||||
ip->ip_dst.s_addr = ip_dst->s_addr;
|
||||
|
||||
if (ipoptlen)
|
||||
memcpy((u8*)ip + sizeof(struct ip), ipopt, ipoptlen);
|
||||
|
||||
// ip options source routing hack:
|
||||
if(ipoptlen && o.ipopt_firsthop && o.ipopt_lasthop) {
|
||||
u8* ipo = (u8*)ip + sizeof(struct ip);
|
||||
struct in_addr *newdst = (struct in_addr *) &ipo[o.ipopt_firsthop];
|
||||
struct in_addr *olddst = (struct in_addr *) &ipo[o.ipopt_lasthop];
|
||||
// our destination is somewhere else :)
|
||||
ip->ip_dst.s_addr = newdst->s_addr;
|
||||
|
||||
// and last hop should be destination
|
||||
olddst->s_addr = ip_dst->s_addr;
|
||||
}
|
||||
|
||||
|
||||
#if HAVE_IP_IP_SUM
|
||||
ip->ip_sum = 0;
|
||||
ip->ip_sum = in_cksum((unsigned short *)ip, sizeof(struct ip) + ipoptlen);
|
||||
#endif
|
||||
return(sizeof(struct ip) + ipoptlen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int send_tcp_raw_decoys( int sd, struct eth_nfo *eth,
|
||||
const struct in_addr *victim, int ttl, bool df,
|
||||
u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved, u8 flags,
|
||||
u16 window, u16 urp, u8 *options, int optlen, char *data,
|
||||
u16 datalen)
|
||||
const struct in_addr *victim,
|
||||
int ttl, bool df,
|
||||
u8* ipopt, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
u32 seq, u32 ack, u8 reserved, u8 flags, u16 window, u16 urp,
|
||||
u8 *options, int optlen,
|
||||
char *data, u16 datalen)
|
||||
{
|
||||
int decoy;
|
||||
|
||||
for(decoy = 0; decoy < o.numdecoys; decoy++)
|
||||
if (send_tcp_raw(sd, eth, &o.decoys[decoy], victim, ttl, df, sport, dport,
|
||||
seq, ack, reserved, flags, window, urp, options, optlen, data,
|
||||
datalen) == -1)
|
||||
if (send_tcp_raw(sd, eth,
|
||||
&o.decoys[decoy], victim,
|
||||
ttl, df,
|
||||
ipopt, ipoptlen,
|
||||
sport, dport,
|
||||
seq, ack, reserved, flags, window, urp,
|
||||
options, optlen,
|
||||
data, datalen) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@@ -1035,11 +1089,13 @@ int send_tcp_raw_decoys( int sd, struct eth_nfo *eth,
|
||||
actually sent by this function. Caller must delete the buffer when
|
||||
finished with the packet. The packet length is returned in
|
||||
packetlen, which must be a valid int pointer. */
|
||||
u8 *build_tcp_raw(const struct in_addr *source,
|
||||
const struct in_addr *victim, int ttl, u16 ipid, bool df,
|
||||
u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved, u8 flags,
|
||||
u16 window, u16 urp, u8 *options, int optlen, char *data,
|
||||
u16 datalen, u32 *packetlen) {
|
||||
u8 *build_tcp_raw(const struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, u16 ipid, u8 tos, bool df,
|
||||
u8 *ipopt, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
u32 seq, u32 ack, u8 reserved, u8 flags, u16 window, u16 urp,
|
||||
u8 *tcpopt, int tcpoptlen,
|
||||
char *data, u16 datalen, u32 *outpacketlen) {
|
||||
|
||||
struct pseudo_header {
|
||||
/*for computing TCP checksum, see TCP/IP Illustrated p. 145 */
|
||||
@@ -1049,18 +1105,22 @@ struct pseudo_header {
|
||||
u8 protocol;
|
||||
u16 length;
|
||||
};
|
||||
u8 *packet = (u8 *) safe_malloc(sizeof(struct ip) + sizeof(struct tcphdr) + optlen + datalen);
|
||||
int packetlen = sizeof(struct ip) + ipoptlen +
|
||||
sizeof(struct tcphdr) + tcpoptlen + datalen;
|
||||
u8 *packet = (u8 *) safe_malloc(packetlen);
|
||||
struct ip *ip = (struct ip *) packet;
|
||||
struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct ip));
|
||||
struct pseudo_header *pseudo = (struct pseudo_header *) (packet + sizeof(struct ip) - sizeof(struct pseudo_header));
|
||||
struct tcphdr *tcp = (struct tcphdr *) ((u8*)ip + sizeof(struct ip) + ipoptlen);
|
||||
struct pseudo_header *pseudo =
|
||||
(struct pseudo_header *) ((u8*)tcp - sizeof(struct pseudo_header));
|
||||
static int myttl = 0;
|
||||
|
||||
assert(victim);
|
||||
assert(source);
|
||||
assert(ipoptlen%4==0);
|
||||
|
||||
if (tcpoptlen % 4)
|
||||
fatal("build_tcp_raw() called with an option length argument of %d which is illegal because it is not divisible by 4. Just add \\0 padding to the end.", tcpoptlen);
|
||||
|
||||
if (optlen % 4) {
|
||||
fatal("build_tcp_raw() called with an option length argument of %d which is illegal because it is not divisible by 4. Just add \\0 padding to the end.", optlen);
|
||||
}
|
||||
|
||||
/* Time to live */
|
||||
if (ttl == -1) {
|
||||
@@ -1069,19 +1129,19 @@ if (ttl == -1) {
|
||||
myttl = ttl;
|
||||
}
|
||||
|
||||
memset((char *) packet, 0, sizeof(struct ip) + sizeof(struct tcphdr));
|
||||
|
||||
pseudo->s_addy = source->s_addr;
|
||||
pseudo->d_addr = victim->s_addr;
|
||||
pseudo->zer0 = 0;
|
||||
pseudo->protocol = IPPROTO_TCP;
|
||||
pseudo->length = htons(sizeof(struct tcphdr) + optlen + datalen);
|
||||
pseudo->length = htons(sizeof(struct tcphdr) + tcpoptlen + datalen);
|
||||
|
||||
/* Fill tcp header */
|
||||
memset(tcp, 0, sizeof(struct tcphdr));
|
||||
tcp->th_sport = htons(sport);
|
||||
tcp->th_dport = htons(dport);
|
||||
if (seq) {
|
||||
tcp->th_seq = htonl(seq);
|
||||
}
|
||||
else if (flags & TH_SYN) {
|
||||
} else if (flags & TH_SYN) {
|
||||
get_random_bytes(&(tcp->th_seq), 4);
|
||||
}
|
||||
|
||||
@@ -1092,7 +1152,7 @@ if (ack)
|
||||
|
||||
if (reserved)
|
||||
tcp->th_x2 = reserved & 0x0F;
|
||||
tcp->th_off = 5 + (optlen /4) /*words*/;
|
||||
tcp->th_off = 5 + (tcpoptlen /4) /*words*/;
|
||||
tcp->th_flags = flags;
|
||||
|
||||
if (window)
|
||||
@@ -1103,62 +1163,50 @@ else tcp->th_win = htons(1024 * (myttl % 4 + 1)); /* Who cares */
|
||||
if (urp)
|
||||
tcp->th_urp = htons(urp);
|
||||
|
||||
/* We should probably copy the data over too */
|
||||
if (data && datalen)
|
||||
memcpy(packet + sizeof(struct ip) + sizeof(struct tcphdr) + optlen, data, datalen);
|
||||
/* And the options */
|
||||
if (optlen) {
|
||||
memcpy(packet + sizeof(struct ip) + sizeof(struct tcphdr), options, optlen);
|
||||
}
|
||||
/* And the options */
|
||||
if (tcpoptlen)
|
||||
memcpy((u8*)tcp + sizeof(struct tcphdr), tcpopt, tcpoptlen);
|
||||
/* We should probably copy the data over too */
|
||||
if (data && datalen)
|
||||
memcpy((u8*)tcp + sizeof(struct tcphdr) + tcpoptlen, data, datalen);
|
||||
|
||||
#if STUPID_SOLARIS_CHECKSUM_BUG
|
||||
tcp->th_sum = sizeof(struct tcphdr) + optlen + datalen;
|
||||
tcp->th_sum = sizeof(struct tcphdr) + tcpoptlen + datalen;
|
||||
#else
|
||||
tcp->th_sum = in_cksum((unsigned short *)pseudo, sizeof(struct tcphdr) +
|
||||
optlen + sizeof(struct pseudo_header) + datalen);
|
||||
tcpoptlen + sizeof(struct pseudo_header) + datalen);
|
||||
#endif
|
||||
|
||||
if ( o.badsum )
|
||||
--tcp->th_sum;
|
||||
|
||||
/* Now for the ip header */
|
||||
memset(packet, 0, sizeof(struct ip));
|
||||
ip->ip_v = 4;
|
||||
ip->ip_hl = 5;
|
||||
ip->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + optlen + datalen);
|
||||
get_random_bytes(&(ip->ip_id), 2);
|
||||
ip->ip_ttl = myttl;
|
||||
ip->ip_p = IPPROTO_TCP;
|
||||
ip->ip_id = ipid;
|
||||
if(df) ip->ip_off |= htons(IP_DF);
|
||||
ip->ip_src.s_addr = source->s_addr;
|
||||
#ifdef WIN32
|
||||
// I'm not sure why this is --Fyodor
|
||||
if (source->s_addr == victim->s_addr) ip->ip_src.s_addr++;
|
||||
#endif
|
||||
fill_ip_raw(ip, packetlen, ipopt, ipoptlen,
|
||||
tos, ipid, df?IP_DF:0, myttl, IPPROTO_TCP,
|
||||
source, victim);
|
||||
|
||||
ip->ip_dst.s_addr= victim->s_addr;
|
||||
#if HAVE_IP_IP_SUM
|
||||
ip->ip_sum = in_cksum((unsigned short *)ip, sizeof(struct ip));
|
||||
#endif
|
||||
|
||||
*packetlen = ntohs(ip->ip_len);
|
||||
*outpacketlen = packetlen;
|
||||
return packet;
|
||||
|
||||
}
|
||||
|
||||
/* You need to call sethdrinclude(sd) on the sending sd before calling this */
|
||||
int send_tcp_raw( int sd, struct eth_nfo *eth, const struct in_addr *source,
|
||||
const struct in_addr *victim, int ttl, bool df,
|
||||
u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved, u8 flags,
|
||||
u16 window, u16 urp, u8 *options, int optlen, char *data,
|
||||
u16 datalen)
|
||||
int send_tcp_raw( int sd, struct eth_nfo *eth,
|
||||
const struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, bool df,
|
||||
u8* ipops, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
u32 seq, u32 ack, u8 reserved, u8 flags,u16 window, u16 urp,
|
||||
u8 *options, int optlen,
|
||||
char *data, u16 datalen)
|
||||
{
|
||||
unsigned int packetlen;
|
||||
int res = -1;
|
||||
|
||||
u8 *packet = build_tcp_raw(source, victim, ttl, get_random_u16(), df, sport,
|
||||
dport, seq, ack, reserved, flags, window, urp, options, optlen,
|
||||
u8 *packet = build_tcp_raw(source, victim,
|
||||
ttl, get_random_u16(), IP_TOS_DEFAULT, df,
|
||||
ipops, ipoptlen,
|
||||
sport, dport,
|
||||
seq, ack, reserved, flags, window, urp,
|
||||
options, optlen,
|
||||
data, datalen, &packetlen);
|
||||
if (!packet) return -1;
|
||||
res = send_ip_packet(sd, eth, packet, packetlen);
|
||||
@@ -1325,9 +1373,10 @@ int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetl
|
||||
packetlen, which must be a valid int pointer. The id/seq will be converted
|
||||
to network byte order (if it differs from HBO) */
|
||||
u8 *build_icmp_raw(const struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, u16 ipid, u8 tos, bool df, u16 seq,
|
||||
unsigned short id, u8 ptype, u8 pcode, char *data,
|
||||
u16 datalen, u32 *packetlen) {
|
||||
int ttl, u16 ipid, u8 tos, bool df,
|
||||
u8 *ipopt, int ipoptlen,
|
||||
u16 seq, unsigned short id, u8 ptype, u8 pcode,
|
||||
char *data, u16 datalen, u32 *packetlen) {
|
||||
|
||||
struct ppkt {
|
||||
u8 type;
|
||||
@@ -1373,8 +1422,12 @@ pingpkt.checksum = in_cksum((unsigned short *)ping, icmplen);
|
||||
if ( o.badsum )
|
||||
--pingpkt.checksum;
|
||||
|
||||
return build_ip_raw(source, victim, o.ttl, IPPROTO_ICMP, get_random_u16(), tos, df,
|
||||
ping, icmplen, packetlen);
|
||||
return build_ip_raw(source, victim,
|
||||
IPPROTO_ICMP,
|
||||
o.ttl, get_random_u16(), tos, df,
|
||||
ipopt, ipoptlen,
|
||||
ping, icmplen,
|
||||
packetlen);
|
||||
}
|
||||
|
||||
|
||||
@@ -1485,14 +1538,17 @@ if (ip->ip_p== IPPROTO_UDP) {
|
||||
}
|
||||
|
||||
int send_udp_raw_decoys( int sd, struct eth_nfo *eth,
|
||||
const struct in_addr *victim, int ttl,
|
||||
u16 sport, u16 dport, u16 ipid, char *data,
|
||||
u16 datalen) {
|
||||
const struct in_addr *victim,
|
||||
int ttl, u16 ipid,
|
||||
u8* ipops, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
char *data, u16 datalen) {
|
||||
int decoy;
|
||||
|
||||
for(decoy = 0; decoy < o.numdecoys; decoy++)
|
||||
if (send_udp_raw(sd, eth, &o.decoys[decoy], victim, ttl, sport, dport, ipid,
|
||||
data, datalen) == -1)
|
||||
if (send_udp_raw(sd, eth, &o.decoys[decoy], victim,
|
||||
ttl, ipid, ipops, ipoptlen,
|
||||
sport, dport, data, datalen) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@@ -1506,30 +1562,30 @@ int send_udp_raw_decoys( int sd, struct eth_nfo *eth,
|
||||
finished with the packet. The packet length is returned in
|
||||
packetlen, which must be a valid int pointer. */
|
||||
u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, u16 sport, u16 dport, u16 ipid, char *data,
|
||||
u16 datalen, u32 *packetlen)
|
||||
int ttl, u16 ipid, u8 tos, bool df,
|
||||
u8 *ipopt, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
char *data, u16 datalen, u32 *outpacketlen)
|
||||
{
|
||||
unsigned char *packet = (unsigned char *) safe_malloc(sizeof(struct ip) + sizeof(udphdr_bsd) + datalen);
|
||||
int packetlen = sizeof(struct ip) + ipoptlen + sizeof(udphdr_bsd) + datalen;
|
||||
u8 *packet = (u8 *) safe_malloc(packetlen);
|
||||
struct ip *ip = (struct ip *) packet;
|
||||
udphdr_bsd *udp = (udphdr_bsd *) (packet + sizeof(struct ip));
|
||||
udphdr_bsd *udp = (udphdr_bsd *) ((u8*)ip + sizeof(struct ip) + ipoptlen);
|
||||
static int myttl = 0;
|
||||
|
||||
struct pseudo_udp_hdr {
|
||||
struct in_addr source;
|
||||
struct in_addr dest;
|
||||
u8 zero;
|
||||
u8 zer0;
|
||||
u8 proto;
|
||||
u16 length;
|
||||
} *pseudo = (struct pseudo_udp_hdr *) ((char *)udp - 12) ;
|
||||
} *pseudo = (struct pseudo_udp_hdr *) ((u8 *)udp - sizeof(struct pseudo_udp_hdr));
|
||||
|
||||
*packetlen = 0;
|
||||
|
||||
/* check that required fields are there and not too silly */
|
||||
if ( !victim) {
|
||||
fprintf(stderr, "build_udp_raw: One or more of your parameters suck!\n");
|
||||
free(packet);
|
||||
return NULL;
|
||||
}
|
||||
assert(victim);
|
||||
assert(source);
|
||||
assert(ipoptlen%4==0);
|
||||
|
||||
/* Time to live */
|
||||
if (ttl == -1) {
|
||||
@@ -1538,19 +1594,19 @@ u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim,
|
||||
myttl = ttl;
|
||||
}
|
||||
|
||||
memset((char *) packet, 0, sizeof(struct ip) + sizeof(udphdr_bsd));
|
||||
|
||||
udp->uh_sport = htons(sport);
|
||||
udp->uh_dport = htons(dport);
|
||||
udp->uh_ulen = htons(8 + datalen);
|
||||
udp->uh_sum = 0;
|
||||
udp->uh_ulen = htons(sizeof(udphdr_bsd) + datalen);
|
||||
|
||||
/* We should probably copy the data over too */
|
||||
if (data)
|
||||
memcpy(packet + sizeof(struct ip) + sizeof(udphdr_bsd), data, datalen);
|
||||
memcpy((u8*)udp + sizeof(udphdr_bsd), data, datalen);
|
||||
|
||||
/* Now the pseudo header for checksuming */
|
||||
pseudo->source.s_addr = source->s_addr;
|
||||
pseudo->dest.s_addr = victim->s_addr;
|
||||
pseudo->zer0 = 0;
|
||||
pseudo->proto = IPPROTO_UDP;
|
||||
pseudo->length = htons(sizeof(udphdr_bsd) + datalen);
|
||||
|
||||
@@ -1564,39 +1620,28 @@ u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim,
|
||||
if ( o.badsum )
|
||||
--udp->uh_sum;
|
||||
|
||||
/* Goodbye, pseudo header! */
|
||||
memset(pseudo, 0, sizeof(*pseudo));
|
||||
fill_ip_raw(ip, packetlen, ipopt, ipoptlen,
|
||||
tos, ipid, df?IP_DF:0, myttl, IPPROTO_UDP,
|
||||
source, victim);
|
||||
|
||||
/* Now for the ip header */
|
||||
ip->ip_v = 4;
|
||||
ip->ip_hl = 5;
|
||||
ip->ip_len = htons(sizeof(struct ip) + sizeof(udphdr_bsd) + datalen);
|
||||
ip->ip_id = htons(ipid);
|
||||
ip->ip_ttl = myttl;
|
||||
ip->ip_p = IPPROTO_UDP;
|
||||
ip->ip_src.s_addr = source->s_addr;
|
||||
#ifdef WIN32
|
||||
// I'm not exactly sure why this is needed --Fyodor
|
||||
if(source->s_addr == victim->s_addr) ip->ip_src.s_addr;
|
||||
#endif
|
||||
ip->ip_dst.s_addr= victim->s_addr;
|
||||
#if HAVE_IP_IP_SUM
|
||||
ip->ip_sum = in_cksum((unsigned short *)ip, sizeof(struct ip));
|
||||
#endif
|
||||
|
||||
*packetlen = ntohs(ip->ip_len);
|
||||
*outpacketlen = packetlen;
|
||||
return packet;
|
||||
}
|
||||
|
||||
int send_udp_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
|
||||
const struct in_addr *victim,
|
||||
int ttl, u16 sport, u16 dport, u16 ipid, char *data,
|
||||
u16 datalen)
|
||||
int send_udp_raw( int sd, struct eth_nfo *eth,
|
||||
struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, u16 ipid,
|
||||
u8* ipopt, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
char *data, u16 datalen)
|
||||
{
|
||||
unsigned int packetlen;
|
||||
int res = -1;
|
||||
u8 *packet = build_udp_raw(source, victim, ttl, sport, dport, ipid, data,
|
||||
datalen, &packetlen);
|
||||
u8 *packet = build_udp_raw(source, victim,
|
||||
ttl, ipid, IP_TOS_DEFAULT, false,
|
||||
ipopt, ipoptlen,
|
||||
sport, dport,
|
||||
data, datalen, &packetlen);
|
||||
if (!packet) return -1;
|
||||
res = send_ip_packet(sd, eth, packet, packetlen);
|
||||
|
||||
@@ -1611,20 +1656,21 @@ int send_udp_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
|
||||
finished with the packet. The packet length is returned in
|
||||
packetlen, which must be a valid int pointer. */
|
||||
u8 *build_ip_raw(const struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, u8 proto, u16 ipid, u8 tos, bool df, char *data, u16 datalen,
|
||||
u32 *packetlen)
|
||||
u8 proto,
|
||||
int ttl, u16 ipid, u8 tos, bool df,
|
||||
u8 *ipopt, int ipoptlen,
|
||||
char *data, u16 datalen,
|
||||
u32 *outpacketlen)
|
||||
{
|
||||
|
||||
unsigned char *packet = (unsigned char *) safe_malloc(sizeof(struct ip) + datalen);
|
||||
int packetlen = sizeof(struct ip) + ipoptlen + datalen;
|
||||
u8 *packet = (u8 *) safe_malloc(packetlen);
|
||||
struct ip *ip = (struct ip *) packet;
|
||||
static int myttl = 0;
|
||||
|
||||
/* check that required fields are there and not too silly */
|
||||
if ( !victim) {
|
||||
fprintf(stderr, "send_ip_raw: One or more of your parameters suck!\n");
|
||||
free(packet);
|
||||
return NULL;
|
||||
}
|
||||
assert(source);
|
||||
assert(victim);
|
||||
assert(ipoptlen%4==0);
|
||||
|
||||
/* Time to live */
|
||||
if (ttl == -1) {
|
||||
@@ -1633,47 +1679,34 @@ if (ttl == -1) {
|
||||
myttl = ttl;
|
||||
}
|
||||
|
||||
memset((char *) packet, 0, sizeof(struct ip));
|
||||
|
||||
/* Now for the ip header */
|
||||
|
||||
ip->ip_v = 4;
|
||||
ip->ip_hl = 5;
|
||||
ip->ip_tos = tos;
|
||||
ip->ip_len = htons(sizeof(struct ip) + datalen);
|
||||
ip->ip_id = htons(ipid);
|
||||
if(df) ip->ip_off |= htons(IP_DF);
|
||||
ip->ip_ttl = myttl;
|
||||
ip->ip_p = proto;
|
||||
ip->ip_src.s_addr = source->s_addr;
|
||||
// #ifdef WIN32
|
||||
// TODO: Should this be removed? I'm not sure why this is here -- Fyodor
|
||||
// if(source->s_addr == victim->s_addr) ip->ip_src.s_addr++;
|
||||
// #endif
|
||||
ip->ip_dst.s_addr = victim->s_addr;
|
||||
#if HAVE_IP_IP_SUM
|
||||
ip->ip_sum = in_cksum((unsigned short *)ip, sizeof(struct ip));
|
||||
#endif
|
||||
fill_ip_raw(ip, packetlen, ipopt, ipoptlen,
|
||||
tos, ipid, df?IP_DF:0, myttl, proto,
|
||||
source, victim);
|
||||
|
||||
/* We should probably copy the data over too */
|
||||
if (data)
|
||||
memcpy(packet + sizeof(struct ip), data, datalen);
|
||||
memcpy((u8*)ip + sizeof(struct ip) + ipoptlen, data, datalen);
|
||||
|
||||
*packetlen = ntohs(ip->ip_len);
|
||||
*outpacketlen = packetlen;
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
||||
/* You need to call sethdrinclude(sd) on the sending sd before calling this */
|
||||
int send_ip_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
|
||||
const struct in_addr *victim, int ttl, u8 proto,
|
||||
int send_ip_raw( int sd, struct eth_nfo *eth,
|
||||
struct in_addr *source, const struct in_addr *victim,
|
||||
u8 proto, int ttl,
|
||||
u8* ipopt, int ipoptlen,
|
||||
char *data, u16 datalen)
|
||||
{
|
||||
unsigned int packetlen;
|
||||
int res = -1;
|
||||
|
||||
u8 *packet = build_ip_raw(source, victim, ttl, proto, get_random_u16(),
|
||||
IP_TOS_DEFAULT, false, data, datalen, &packetlen);
|
||||
u8 *packet = build_ip_raw(source, victim,
|
||||
proto,
|
||||
ttl, get_random_u16(), IP_TOS_DEFAULT, false,
|
||||
ipopt, ipoptlen,
|
||||
data, datalen, &packetlen);
|
||||
if (!packet) return -1;
|
||||
|
||||
res = send_ip_packet(sd, eth, packet, packetlen);
|
||||
|
||||
73
tcpip.h
73
tcpip.h
@@ -515,17 +515,25 @@ unsigned short in_cksum(u16 *ptr,int nbytes);
|
||||
|
||||
/* Build and send a raw tcp packet. If TTL is -1, a partially random
|
||||
(but likely large enough) one is chosen */
|
||||
int send_tcp_raw( int sd, struct eth_nfo *eth, const struct in_addr *source,
|
||||
const struct in_addr *victim, int ttl, bool df,
|
||||
u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved, u8 flags,
|
||||
u16 window, u16 urp, u8 *options, int optlen, char *data,
|
||||
u16 datalen);
|
||||
int send_udp_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
|
||||
const struct in_addr *victim, int ttl, u16 sport,
|
||||
u16 dport, u16 ipid, char *data, u16 datalen);
|
||||
int send_tcp_raw( int sd, struct eth_nfo *eth,
|
||||
const struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, bool df,
|
||||
u8* ipopt, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
u32 seq, u32 ack, u8 reserved, u8 flags, u16 window, u16 urp,
|
||||
u8 *options, int optlen,
|
||||
char *data, u16 datalen);
|
||||
int send_udp_raw( int sd, struct eth_nfo *eth,
|
||||
struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, u16 ipid,
|
||||
u8* ipopt, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
char *data, u16 datalen);
|
||||
|
||||
int send_ip_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
|
||||
const struct in_addr *victim, int ttl, u8 proto,
|
||||
int send_ip_raw( int sd, struct eth_nfo *eth,
|
||||
struct in_addr *source, const struct in_addr *victim,
|
||||
u8 proto, int ttl,
|
||||
u8* ipopt, int ipoptlen,
|
||||
char *data, u16 datalen);
|
||||
|
||||
/* Builds a TCP packet (including an IP header) by packing the fields
|
||||
@@ -535,8 +543,12 @@ int send_ip_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
|
||||
finished with the packet. The packet length is returned in
|
||||
packetlen, which must be a valid int pointer. */
|
||||
u8 *build_tcp_raw(const struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, u16 ipid, bool df, u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved,
|
||||
u8 flags, u16 window, u16 urp, u8 *options, int optlen, char *data, u16 datalen,
|
||||
int ttl, u16 ipid, u8 tos, bool df,
|
||||
u8* ipopt, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
u32 seq, u32 ack, u8 reserved, u8 flags, u16 window, u16 urp,
|
||||
u8 *options, int optlen,
|
||||
char *data, u16 datalen,
|
||||
u32 *packetlen);
|
||||
|
||||
/* Builds a UDP packet (including an IP header) by packing the fields
|
||||
@@ -546,8 +558,11 @@ u8 *build_tcp_raw(const struct in_addr *source, const struct in_addr *victim,
|
||||
finished with the packet. The packet length is returned in
|
||||
packetlen, which must be a valid int pointer. */
|
||||
u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, u16 sport, u16 dport, u16 ipid, char *data,
|
||||
u16 datalen, u32 *packetlen);
|
||||
int ttl, u16 ipid, u8 tos, bool df,
|
||||
u8* ipopt, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
char *data, u16 datalen,
|
||||
u32 *packetlen);
|
||||
|
||||
/* Builds an ICMP packet (including an IP header) by packing the
|
||||
fields with the given information. It allocates a new buffer to
|
||||
@@ -558,8 +573,10 @@ u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim,
|
||||
id/seq will be converted to network byte order (if it differs from
|
||||
HBO) */
|
||||
u8 *build_icmp_raw(const struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, u16 ipid, u8 tos, bool df, u16 seq, unsigned short id, u8 ptype,
|
||||
u8 pcode, char *data, u16 datalen, u32 *packetlen);
|
||||
int ttl, u16 ipid, u8 tos, bool df,
|
||||
u8* ipopt, int ipoptlen,
|
||||
u16 seq, unsigned short id, u8 ptype, u8 pcode,
|
||||
char *data, u16 datalen, u32 *packetlen);
|
||||
|
||||
/* Builds an IP packet (including an IP header) by packing the fields
|
||||
with the given information. It allocates a new buffer to store the
|
||||
@@ -568,7 +585,10 @@ u8 *build_icmp_raw(const struct in_addr *source, const struct in_addr *victim,
|
||||
finished with the packet. The packet length is returned in
|
||||
packetlen, which must be a valid int pointer. */
|
||||
u8 *build_ip_raw(const struct in_addr *source, const struct in_addr *victim,
|
||||
int ttl, u8 proto, u16 ipid, u8 tos, bool df, char *data, u16 datalen,
|
||||
u8 proto,
|
||||
int ttl, u16 ipid, u8 tos, bool df,
|
||||
u8* ipopt, int ipoptlen,
|
||||
char *data, u16 datalen,
|
||||
u32 *packetlen);
|
||||
|
||||
/* Send a pre-built IPv4 packet */
|
||||
@@ -577,15 +597,20 @@ int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet,
|
||||
|
||||
/* Decoy versions of the raw packet sending functions ... */
|
||||
int send_tcp_raw_decoys( int sd, struct eth_nfo *eth,
|
||||
const struct in_addr *victim, int ttl, bool df,
|
||||
u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved, u8 flags,
|
||||
u16 window, u16 urp, u8 *options, int optlen, char *data,
|
||||
u16 datalen);
|
||||
const struct in_addr *victim,
|
||||
int ttl, bool df,
|
||||
u8* ipopt, int ipoptlen,
|
||||
u16 sport, u16 dport,
|
||||
u32 seq, u32 ack, u8 reserved, u8 flags, u16 window, u16 urp,
|
||||
u8 *options, int optlen,
|
||||
char *data, u16 datalen);
|
||||
|
||||
int send_udp_raw_decoys( int sd, struct eth_nfo *eth,
|
||||
const struct in_addr *victim, int ttl,
|
||||
u16 sport, u16 dport, u16 ipid, char *data,
|
||||
u16 datalen);
|
||||
const struct in_addr *victim,
|
||||
int ttl, u16 ipid,
|
||||
u8* ipops, int ip,
|
||||
u16 sport, u16 dport,
|
||||
char *data, u16 datalen);
|
||||
|
||||
|
||||
/* Calls pcap_open_live and spits out an error (and quits) if the call fails.
|
||||
|
||||
355
utils.cc
355
utils.cc
@@ -99,6 +99,7 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "nmap.h"
|
||||
#include "utils.h"
|
||||
#include "NmapOps.h"
|
||||
|
||||
@@ -559,6 +560,360 @@ char *cstring_unescape(char *str, unsigned int *newlen) {
|
||||
return str;
|
||||
}
|
||||
|
||||
/* This function converts zero-terminated 'txt' string to binary 'data'.
|
||||
It is used to parse user input for ip options. Some examples of possible input
|
||||
strings and results:
|
||||
'\x01*2\xA2' -> [0x01,0x01,0xA2] // with 'x' number is parsed in hex
|
||||
'\01\01\255' -> [0x01,0x01,0xFF] // without 'x' its in decimal
|
||||
'\x01\x00*2' -> [0x01,0x00,0x00] // '*' is copying char
|
||||
'R' -> Record Route with 9 slots
|
||||
'S 192.168.0.1 172.16.0.1' -> Strict Route with 2 slots
|
||||
'L 192.168.0.1 172.16.0.1' -> Loose Route with 2 slots
|
||||
'T' -> Record Timestamp with 9 slots
|
||||
'U' -> Record Timestamp and Ip Address with 4 slots
|
||||
*/
|
||||
int parse_ip_options(char *txt, u8 *data, int datalen, int* firsthopoff, int* lasthopoff){
|
||||
enum{
|
||||
NONE = 0,
|
||||
SLASH = 1,
|
||||
MUL = 2,
|
||||
RR = 3,
|
||||
TIME = 4,
|
||||
} s = NONE;
|
||||
char *n, lc;
|
||||
char *c = txt;
|
||||
u8 *d = data;
|
||||
int i,j;
|
||||
int base = 10;
|
||||
u8 *dataend = &data[datalen];
|
||||
u8 *len = NULL;
|
||||
char buf[32];
|
||||
memset(data, 0, datalen);
|
||||
bool sourcerouting = false;
|
||||
|
||||
|
||||
for(;*c;c++){
|
||||
switch(s){
|
||||
case SLASH:
|
||||
// parse \x00 string
|
||||
if(*c == 'x'){// just ignore this char
|
||||
base = 16;
|
||||
break;
|
||||
}
|
||||
if(isxdigit(*c)){
|
||||
*d++ = strtol(c, &n, base);
|
||||
c=n-1;
|
||||
}else
|
||||
fatal("not a digit after '\\'");
|
||||
s = NONE;
|
||||
break;
|
||||
case MUL:
|
||||
if(d==data)
|
||||
fatal("nothing before '*' char");
|
||||
i = strtol(c, &n, 10);
|
||||
if(i<2)
|
||||
fatal("bad number after '*'");
|
||||
c = n-1; // move current txt pointer
|
||||
lc = *(d-1); // last char, we'll copy this
|
||||
for(j=1; j<i; j++){
|
||||
*d++ = lc;
|
||||
if(d == dataend) // check for overflow
|
||||
goto after;
|
||||
}
|
||||
s = NONE;
|
||||
break;
|
||||
case RR:
|
||||
if(*c==' ' || *c==',')
|
||||
break;
|
||||
n = buf;
|
||||
while(*c=='.' || (*c>='0' && *c<='9') && n-buf <= ((int)sizeof(buf)-1))
|
||||
*n++ = *c++;
|
||||
*n = '\0'; c--;
|
||||
if(d+4>=dataend)
|
||||
fatal("Buffer too small. Or input data too big :)");
|
||||
i = inet_pton(AF_INET, buf, d);
|
||||
if(i<1)
|
||||
fatal("Not a valid ipv4 address '%s'",buf);
|
||||
// remember offset of first hop
|
||||
if(sourcerouting && !*firsthopoff)
|
||||
*firsthopoff = d - data;
|
||||
d+=4;
|
||||
if(*len<37)
|
||||
*len += 4;
|
||||
break;
|
||||
case TIME:
|
||||
fatal("No more arguments allowed!");
|
||||
default:
|
||||
switch(*c){
|
||||
case '\\':s = SLASH;base=10;break;
|
||||
case '*':s = MUL;break;
|
||||
case 'R':
|
||||
case 'S':
|
||||
case 'L':
|
||||
if(d != data)
|
||||
fatal("This option can't be used in that way");
|
||||
*d++ = '\x01';//NOP
|
||||
switch(*c){
|
||||
case 'R':*d++ = 7;break;
|
||||
case 'S':*d++ = 137; sourcerouting=true; break;
|
||||
case 'L':*d++ = 131; sourcerouting=true; break;
|
||||
}
|
||||
len = d;
|
||||
*d++ = (*c=='R')? 39 : 3; // length: 3+4*9 bytes
|
||||
*d++ = 4; //pointer
|
||||
s = RR;
|
||||
break;
|
||||
case 'T':
|
||||
case 'U':
|
||||
if(d != data)
|
||||
fatal("This option can't be used in that way");
|
||||
*d++ = 68; // option type
|
||||
len = d;
|
||||
*d++ = (*c=='U') ? 36 : 40; // length: 3+4*9 bytes or 4+4*9 bytes
|
||||
*d++ = 5; // pointer
|
||||
*d++ = (*c=='U') ? 1 : 0; // flag: address and Time fields
|
||||
s = TIME;
|
||||
break;
|
||||
default://*d++ = *c;
|
||||
fatal("Bad character in ip option '%c'",*c);
|
||||
}
|
||||
}
|
||||
if(d == dataend)
|
||||
break;
|
||||
assert(d<dataend);
|
||||
}
|
||||
if(sourcerouting){
|
||||
if(*len<37){
|
||||
*len+=4;
|
||||
*lasthopoff = d - data;
|
||||
*d++ = 0;*d++ = 0;*d++ = 0;*d++ = 0;
|
||||
}else
|
||||
fatal("When using source routing you must leave at least one slot for target's ip.");
|
||||
}
|
||||
if(s == RR)
|
||||
return(*len+1); // because we inject NOP before
|
||||
if(s == TIME)
|
||||
return(*len);
|
||||
after:
|
||||
return(d - data);
|
||||
}
|
||||
|
||||
void bintohexstr(char *buf, int buflen, char *src, int srclen){
|
||||
int bp=0;
|
||||
int i;
|
||||
for(i=0; i<srclen; i++){
|
||||
bp += snprintf(buf+bp, buflen-bp, "\\x%02hhx",src[i]);
|
||||
if(bp >= buflen)break;
|
||||
if(i%16==7){
|
||||
bp += snprintf(buf+bp, buflen-bp," ");
|
||||
if(bp >= buflen)break;
|
||||
}
|
||||
if(i%16==15){
|
||||
bp += snprintf(buf+bp, buflen-bp,"\n");
|
||||
if(bp >= buflen)break;
|
||||
}
|
||||
}
|
||||
if(i%16!=0 && bp < buflen)
|
||||
bp += snprintf(buf+bp, buflen-bp,"\n");
|
||||
}
|
||||
|
||||
static inline char* STRAPP(char *fmt, ...) {
|
||||
static char buf[256];
|
||||
static int bp;
|
||||
int left = (int)sizeof(buf)-bp;
|
||||
if(!fmt){
|
||||
bp = 0;
|
||||
return(buf);
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
bp += vsnprintf (buf+bp, (left>0 ? left : 0), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return(buf);
|
||||
}
|
||||
|
||||
#define HEXDUMP -2
|
||||
#define UNKNOWN -1
|
||||
|
||||
#define BREAK() \
|
||||
{option_type = HEXDUMP; break;}
|
||||
#define CHECK(tt) \
|
||||
if(tt >= option_end) \
|
||||
{option_type = HEXDUMP; break;}
|
||||
/* It tries to decode ip options.
|
||||
Returns static buffer. watch out. */
|
||||
char* print_ip_options(u8* ipopt, int ipoptlen) {
|
||||
char ipstring[32];
|
||||
int option_type = UNKNOWN;// option type
|
||||
int option_len = 0; // option length
|
||||
int option_pt = 0; // option pointer
|
||||
int option_fl = 0; // option flag
|
||||
u8 *tptr; // temp pointer
|
||||
u32 *tint; // temp int
|
||||
|
||||
int option_sta = 0; // option start offset
|
||||
int option_end = 0; // option end offset
|
||||
int pt = 0; // current offset
|
||||
|
||||
// clear buffer
|
||||
STRAPP(NULL,NULL);
|
||||
|
||||
if(!ipoptlen)
|
||||
return(NULL);
|
||||
|
||||
while(pt<ipoptlen){ // for every char in ipopt
|
||||
// read ip option header
|
||||
if(option_type == UNKNOWN) {
|
||||
option_sta = pt;
|
||||
option_type = ipopt[pt++];
|
||||
if(option_type != 0 && option_type != 1) { // should we be interested in length field?
|
||||
if(pt >= ipoptlen) // no more chars
|
||||
{option_type = HEXDUMP;pt--; option_end = 255; continue;} // no length field, hex dump to the end
|
||||
option_len = ipopt[pt++];
|
||||
// end must not be greater than length
|
||||
option_end = MIN(option_sta + option_len, ipoptlen);
|
||||
// end must not be smaller than current position
|
||||
option_end = MAX(option_end, option_sta+2);
|
||||
}
|
||||
}
|
||||
switch(option_type) {
|
||||
case 0: // IPOPT_END
|
||||
STRAPP(" EOL", NULL);
|
||||
option_type = UNKNOWN;
|
||||
break;
|
||||
case 1: // IPOPT_NOP
|
||||
STRAPP(" NOP", NULL);
|
||||
option_type = UNKNOWN;
|
||||
break;
|
||||
/* case 130: // IPOPT_SECURITY
|
||||
option_type=-1;
|
||||
break;*/
|
||||
case 131: // IPOPT_LSRR -> Loose Source and Record Route
|
||||
case 137: // IPOPT_SSRR -> Strict Source and Record Route
|
||||
case 7: // IPOPT_RR -> Record Route
|
||||
if(pt - option_sta == 2) {
|
||||
STRAPP(" %s%s{", (option_type==131)?"LS":(option_type==137)?"SS":"", "RR");
|
||||
// option pointer
|
||||
CHECK(pt);
|
||||
option_pt = ipopt[pt++];
|
||||
if(option_pt%4 != 0 || (option_sta + option_pt-1)>option_end || option_pt<4) //bad or too big pointer
|
||||
STRAPP(" [bad ptr=%02i]", option_pt);
|
||||
}
|
||||
if(pt - option_sta > 2) { // ip's
|
||||
int i, s = (option_pt)%4;
|
||||
// if pointer is mangled, fix it. it's max 3 bytes wrong
|
||||
CHECK(pt+3);
|
||||
for(i=0; i<s; i++)
|
||||
STRAPP("\\x%02x", ipopt[pt++]);
|
||||
option_pt -= i;
|
||||
// okay, now we can start printing ip's
|
||||
CHECK(pt+3);
|
||||
tptr = &ipopt[pt]; pt+=4;
|
||||
if(inet_ntop(AF_INET, (char *) tptr, ipstring, sizeof(ipstring)) == NULL)
|
||||
fatal("Failed to convert target address to presentation format!?! Error: %s", strerror(socket_errno()));
|
||||
STRAPP("%c%s",(pt-3-option_sta)==option_pt?'#':' ', ipstring);
|
||||
if(pt == option_end)
|
||||
STRAPP("%s",(pt-option_sta)==(option_pt-1)?"#":""); // pointer in the end?
|
||||
}else BREAK();
|
||||
break;
|
||||
case 68: // IPOPT_TS -> Internet Timestamp
|
||||
if(pt - option_sta == 2){
|
||||
STRAPP(" TM{");
|
||||
// pointer
|
||||
CHECK(pt);
|
||||
option_pt = ipopt[pt++];
|
||||
// bad or too big pointer
|
||||
if(option_pt%4 != 1 || (option_sta + option_pt-1)>option_end || option_pt<5)
|
||||
STRAPP(" [bad ptr=%02i]", option_pt);
|
||||
// flags + overflow
|
||||
CHECK(pt);
|
||||
option_fl = ipopt[pt++];
|
||||
if((option_fl&0x0C) || (option_fl&0x03)==2)
|
||||
STRAPP(" [bad flags=\\x%01hhx]", option_fl&0x0F);
|
||||
STRAPP("[%i hosts not recorded]", option_fl>>4);
|
||||
option_fl &= 0x03;
|
||||
}
|
||||
if(pt - option_sta > 2) {// ip's
|
||||
int i, s = (option_pt+3)%(option_fl==0?4:8);
|
||||
// if pointer is mangled, fix it. it's max 3 bytes wrong
|
||||
CHECK(pt+(option_fl==0?3:7));
|
||||
for(i=0; i<s; i++)
|
||||
STRAPP("\\x%02x", ipopt[pt++]);
|
||||
option_pt-=i;
|
||||
|
||||
// print pt
|
||||
STRAPP("%c",(pt+1-option_sta)==option_pt?'#':' ');
|
||||
// okay, first grab ip.
|
||||
if(option_fl!=0){
|
||||
CHECK(pt+3);
|
||||
tptr = &ipopt[pt]; pt+=4;
|
||||
if(inet_ntop(AF_INET, (char *) tptr, ipstring, sizeof(ipstring)) == NULL)
|
||||
fatal("Failed to convert target address to presentation format!?! Error: %s", strerror(socket_errno()));
|
||||
STRAPP("%s@", ipstring);
|
||||
}
|
||||
CHECK(pt+3);
|
||||
tint = (u32*)&ipopt[pt]; pt+=4;
|
||||
STRAPP("%u", ntohl(*tint));
|
||||
|
||||
if(pt == option_end)
|
||||
STRAPP("%s",(pt-option_sta)==(option_pt-1)?"#":" ");
|
||||
}else BREAK();
|
||||
break;
|
||||
case 136: // IPOPT_SATID -> (SANET) Stream Identifier
|
||||
if(pt - option_sta == 2){
|
||||
u16 *sh;
|
||||
STRAPP(" SI{",NULL);
|
||||
// length
|
||||
if(option_sta+option_len > ipoptlen || option_len!=4)
|
||||
STRAPP("[bad len %02i]", option_len);
|
||||
|
||||
// stream id
|
||||
CHECK(pt+1);
|
||||
sh = (u16*) &ipopt[pt]; pt+=2;
|
||||
option_pt = ntohs(*sh);
|
||||
STRAPP("id=%i", option_pt);
|
||||
if(pt != option_end)
|
||||
BREAK();
|
||||
}else BREAK();
|
||||
break;
|
||||
case UNKNOWN:
|
||||
default:
|
||||
// we read option_type and option_len, print them.
|
||||
STRAPP(" ??{\\x%02hhx\\x%02hhx", option_type, option_len);
|
||||
// check option_end once more:
|
||||
if(option_len < ipoptlen)
|
||||
option_end = MIN(MAX(option_sta+option_len, option_sta+2),ipoptlen);
|
||||
else
|
||||
option_end = 255;
|
||||
option_type = HEXDUMP;
|
||||
break;
|
||||
case HEXDUMP:
|
||||
assert(pt<=option_end);
|
||||
if(pt == option_end){
|
||||
STRAPP("}",NULL);
|
||||
option_type=-1;
|
||||
break;
|
||||
}
|
||||
STRAPP("\\x%02hhx", ipopt[pt++]);
|
||||
break;
|
||||
}
|
||||
if(pt == option_end && option_type != UNKNOWN) {
|
||||
STRAPP("}",NULL);
|
||||
option_type = UNKNOWN;
|
||||
}
|
||||
} // while
|
||||
if(option_type != UNKNOWN)
|
||||
STRAPP("}");
|
||||
|
||||
return(STRAPP("",NULL));
|
||||
}
|
||||
#undef CHECK
|
||||
#undef BREAK
|
||||
#undef UNKNOWN
|
||||
#undef HEXDUMP
|
||||
|
||||
|
||||
/* mmap() an entire file into the address space. Returns a pointer
|
||||
to the beginning of the file. The mmap'ed length is returned
|
||||
inside the length parameter. If there is a problem, NULL is
|
||||
|
||||
18
utils.h
18
utils.h
@@ -226,6 +226,24 @@ long tval2msecs(char *tspec);
|
||||
str is returned. */
|
||||
char *cstring_unescape(char *str, unsigned int *len);
|
||||
|
||||
/* This function converts zero-terminated 'txt' string to binary 'data'.
|
||||
It is used to parse user input for ip options. Some examples of possible input
|
||||
strings and results:
|
||||
'\x01*2\xA2' -> [0x01,0x01,0xA2] // with 'x' number is parsed in hex
|
||||
'\01\01\255' -> [0x01,0x01,0xFF] // without 'x' its in decimal
|
||||
'\x01\x00*2' -> [0x01,0x00,0x00] // '*' is copying char
|
||||
'R' -> Record Route with 9 slots
|
||||
'S 192.168.0.1 172.16.0.1' -> Strict Route with 2 slots
|
||||
'L 192.168.0.1 172.16.0.1' -> Loose Route with 2 slots
|
||||
'T' -> Record Timestamp with 9 slots
|
||||
'U' -> Record Timestamp and Ip Address with 4 slots
|
||||
*/
|
||||
int parse_ip_options(char *txt, u8 *data, int datalen, int* firsthopoff, int* lasthopoff);
|
||||
|
||||
void bintohexstr(char *buf, int buflen, char *src, int srclen);
|
||||
|
||||
char* print_ip_options(u8* ipopt, int ipoptlen);
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
char *strerror(int errnum);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user