1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

o Added initial SCTP port scanning support to Nmap. SCTP is

a layer 4 protocol used mostly for telephony related applications.
  This brings the following new features:
  o SCTP INIT chunk port scan (-sY): open ports return an INIT-ACK
    chunk, closed ones an ABORT chunk.  This is the SCTP equivalent
    of a TCP SYN stealth scan.
  o SCTP COOKIE-ECHO chunk port scan (-sZ): open ports are silent,
    closed ports return an ABORT chunk.
  o SCTP INIT chunk ping probes (-PY): host discovery using SCTP
    INIT chunk packets.
  o SCTP-specific IP protocol scan (-sO -p sctp).
  o SCTP-specific traceroute support (--traceroute).
  o The ability to use the deprecated Adler32 algorithm as specified
    in RFC 2960 instead of CRC32C from RFC 4960 (--adler32).
  o 42 well-known SCTP ports were added to the nmap-services file.
  Part of the work on SCTP support was kindly sponsored by
  Compass Security AG, Switzerland.  [Daniel Roethlisberger]
This commit is contained in:
daniel
2009-06-03 23:15:45 +00:00
parent 99c4008c03
commit 50830f7488
36 changed files with 1333 additions and 152 deletions

View File

@@ -1,5 +1,23 @@
# Nmap Changelog ($Id$); -*-text-*-
o Added initial SCTP port scanning support to Nmap. SCTP is
a layer 4 protocol used mostly for telephony related applications.
This brings the following new features:
o SCTP INIT chunk port scan (-sY): open ports return an INIT-ACK
chunk, closed ones an ABORT chunk. This is the SCTP equivalent
of a TCP SYN stealth scan.
o SCTP COOKIE-ECHO chunk port scan (-sZ): open ports are silent,
closed ports return an ABORT chunk.
o SCTP INIT chunk ping probes (-PY): host discovery using SCTP
INIT chunk packets.
o SCTP-specific IP protocol scan (-sO -p sctp).
o SCTP-specific traceroute support (--traceroute).
o The ability to use the deprecated Adler32 algorithm as specified
in RFC 2960 instead of CRC32C from RFC 4960 (--adler32).
o 42 well-known SCTP ports were added to the nmap-services file.
Part of the work on SCTP support was kindly sponsored by
Compass Security AG, Switzerland. [Daniel Roethlisberger]
o [Zenmap] The Topology tab now has a "Save Snapshot" button that allows
saving the current topology display as PNG, PostScript, PDF, and SVG.
[Joao Medeiros]

View File

@@ -238,6 +238,7 @@ void NmapOps::Initialize() {
max_host_group_sz = 100000; // don't want to be restrictive unless user sets
max_tcp_scan_delay = MAX_TCP_SCAN_DELAY;
max_udp_scan_delay = MAX_UDP_SCAN_DELAY;
max_sctp_scan_delay = MAX_SCTP_SCAN_DELAY;
max_ips_to_scan = 0;
extra_payload_length = 0;
extra_payload = NULL;
@@ -258,6 +259,8 @@ void NmapOps::Initialize() {
listscan = pingscan = allowall = ackscan = bouncescan = connectscan = 0;
rpcscan = nullscan = xmasscan = fragscan = synscan = windowscan = 0;
maimonscan = idlescan = finscan = udpscan = ipprotscan = noresolve = 0;
sctpinitscan = 0;
sctpcookieechoscan = 0;
append_output = 0;
memset(logfd, 0, sizeof(FILE *) * LOG_NUM_FILES);
ttl = -1;
@@ -266,6 +269,7 @@ void NmapOps::Initialize() {
gettimeofday(&start_time, NULL);
pTrace = vTrace = false;
reason = false;
adler32 = false;
if (datadir) free(datadir);
datadir = NULL;
if (xsl_stylesheet) free(xsl_stylesheet);
@@ -305,6 +309,10 @@ void NmapOps::Initialize() {
sourcesocklen = 0;
}
bool NmapOps::SCTPScan() {
return sctpinitscan|sctpcookieechoscan;
}
bool NmapOps::TCPScan() {
return ackscan|bouncescan|connectscan|finscan|idlescan|maimonscan|nullscan|synscan|windowscan|xmasscan;
}
@@ -318,9 +326,9 @@ bool NmapOps::UDPScan() {
IPv6 is being used. It will return false in those cases where a
RawScan is not neccessarily used. */
bool NmapOps::RawScan() {
if (ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|osscan|synscan|udpscan|windowscan|xmasscan)
if (ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|osscan|synscan|udpscan|windowscan|xmasscan|sctpinitscan|sctpcookieechoscan)
return true;
if (pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS|PINGTYPE_TCP_USE_ACK|PINGTYPE_UDP))
if (pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS|PINGTYPE_TCP_USE_ACK|PINGTYPE_UDP|PINGTYPE_SCTP_INIT))
return true;
return false;
@@ -336,11 +344,11 @@ void NmapOps::ValidateOptions() {
/* Insure that at least one scantype is selected */
if (TCPScan() + UDPScan() + ipprotscan + listscan + pingscan == 0) {
if (TCPScan() + UDPScan() + SCTPScan() + ipprotscan + listscan + pingscan == 0) {
if (isr00t && af() == AF_INET)
synscan++;
else connectscan++;
// if (verbose) error("No tcp, udp, or ICMP scantype specified, assuming %s scan. Use -sP if you really don't want to portscan (and just want to see what hosts are up).", synscan? "SYN Stealth" : "vanilla tcp connect()");
// if (verbose) error("No TCP, UDP, SCTP or ICMP scantype specified, assuming %s scan. Use -sP if you really don't want to portscan (and just want to see what hosts are up).", synscan? "SYN Stealth" : "vanilla tcp connect()");
}
if (pingtype != PINGTYPE_NONE && spoofsource) {
@@ -364,11 +372,15 @@ void NmapOps::ValidateOptions() {
fatal("Sorry, UDP Ping (-PU) only works if you are root (because we need to read raw responses off the wire) and only for IPv4 (cause fyodor is too lazy right now to add IPv6 support and nobody has sent a patch)");
}
if ((pingtype & PINGTYPE_SCTP_INIT) && (!isr00t || af() != AF_INET)) {
fatal("Sorry, SCTP INIT Ping (-PY) only works if you are root (because we need to read raw responses off the wire) and only for IPv4 (cause fyodor is too lazy right now to add IPv6 support and nobody has sent a patch)");
}
if ((pingtype & PINGTYPE_PROTO) && (!isr00t || af() != AF_INET)) {
fatal("Sorry, IPProto Ping (-PO) only works if you are root (because we need to read raw responses off the wire) and only for IPv4");
}
if (ipprotscan + (TCPScan() || UDPScan()) + listscan + pingscan > 1) {
if (ipprotscan + (TCPScan() || UDPScan() || SCTPScan()) + listscan + pingscan > 1) {
fatal("Sorry, the IPProtoscan, Listscan, and Pingscan (-sO, -sL, -sP) must currently be used alone rather than combined with other scan types.");
}
@@ -376,7 +388,7 @@ void NmapOps::ValidateOptions() {
fatal("-PN (skip ping) is incompatable with -sP (ping scan). If you only want to enumerate hosts, try list scan (-sL)");
}
if (pingscan && (TCPScan() || UDPScan() || ipprotscan || listscan)) {
if (pingscan && (TCPScan() || UDPScan() || SCTPScan() || ipprotscan || listscan)) {
fatal("Ping scan is not valid with any other scan types (the other ones all include a ping scan");
}
@@ -394,7 +406,7 @@ void NmapOps::ValidateOptions() {
/* We start with stuff users should not do if they are not root */
if (!isr00t) {
if (ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|synscan|udpscan|windowscan|xmasscan) {
if (ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|synscan|udpscan|windowscan|xmasscan|sctpinitscan|sctpcookieechoscan) {
fatal("You requested a scan type which requires %s.", privreq);
}
@@ -477,7 +489,7 @@ void NmapOps::ValidateOptions() {
fatal("--min-rate=%g must be less than or equal to --max-rate=%g", min_packet_send_rate, max_packet_send_rate);
}
if (af() == AF_INET6 && (generate_random_ips|numdecoys|osscan|bouncescan|fragscan|ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|synscan|udpscan|windowscan|xmasscan)) {
if (af() == AF_INET6 && (generate_random_ips|numdecoys|osscan|bouncescan|fragscan|ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|synscan|udpscan|windowscan|xmasscan|sctpinitscan|sctpcookieechoscan)) {
fatal("Sorry -- IPv6 support is currently only available for connect() scan (-sT), ping scan (-sP), and list scan (-sL). OS detection, random targets and decoys are also not supported with IPv6. Further support is under consideration.");
}

View File

@@ -123,6 +123,7 @@ class NmapOps {
bool TCPScan(); /* Returns true if at least one chosen scan type is TCP */
bool UDPScan(); /* Returns true if at least one chosen scan type is UDP */
bool SCTPScan(); /* Returns true if at least one chosen scan type is SCTP */
/* Returns true if at least one chosen scan type uses raw packets.
It does not currently cover cases such as TCP SYN ping scan which
@@ -222,8 +223,10 @@ class NmapOps {
void setMaxHostGroupSz(unsigned int sz);
unsigned int maxTCPScanDelay() { return max_tcp_scan_delay; }
unsigned int maxUDPScanDelay() { return max_udp_scan_delay; }
unsigned int maxSCTPScanDelay() { return max_sctp_scan_delay; }
void setMaxTCPScanDelay(unsigned int delayMS) { max_tcp_scan_delay = delayMS; }
void setMaxUDPScanDelay(unsigned int delayMS) { max_udp_scan_delay = delayMS; }
void setMaxSCTPScanDelay(unsigned int delayMS) { max_sctp_scan_delay = delayMS; }
/* Sets the Name of the XML stylesheet to be printed in XML output.
If this is never called, a default stylesheet distributed with
@@ -291,6 +294,8 @@ class NmapOps {
int rpcscan;
int synscan;
int udpscan;
int sctpinitscan;
int sctpcookieechoscan;
int windowscan;
int xmasscan;
int noresolve;
@@ -314,6 +319,7 @@ class NmapOps {
bool log_errors;
bool traceroute;
bool reason;
bool adler32;
#ifndef NOLUA
int script;
@@ -347,6 +353,7 @@ class NmapOps {
int max_retransmissions;
unsigned int max_tcp_scan_delay;
unsigned int max_udp_scan_delay;
unsigned int max_sctp_scan_delay;
unsigned int min_host_group_sz;
unsigned int max_host_group_sz;
void Initialize();

View File

@@ -58,11 +58,11 @@
<!ENTITY % hostname_types "(PTR)" >
<!-- see output.c:output_xml_scaninfo_records for scan types -->
<!ENTITY % scan_types "(syn|ack|bounce|connect|null|xmas|window|maimon|fin|udp|ipproto)" >
<!ENTITY % scan_types "(syn|ack|bounce|connect|null|xmas|window|maimon|fin|udp|sctpinit|sctpcookieecho|ipproto)" >
<!-- <!ENTITY % ip_versions "(ipv4)" > -->
<!ENTITY % port_protocols "(ip|tcp|udp)" >
<!ENTITY % port_protocols "(ip|tcp|udp|sctp)" >
<!-- I don't know exactly what these are, but the values were enumerated via:
grep "conf=" *

View File

@@ -322,12 +322,12 @@ you would expect.</para>
ubiquitous <application>ping</application> tool. Users can skip
the ping step entirely with a list scan (<option>-sL</option>) or
by disabling ping (<option>-PN</option>), or engage the network
with arbitrary combinations of multi-port TCP SYN/ACK, UDP, and
ICMP probes. The goal of these probes is to solicit responses
which demonstrate that an IP address is actually active (is being
used by a host or network device). On many networks, only a small
percentage of IP addresses are active at any given time. This is
particularly common with private address space
with arbitrary combinations of multi-port TCP SYN/ACK, UDP, SCTP
INIT and ICMP probes. The goal of these probes is to solicit
responses which demonstrate that an IP address is actually active
(is being used by a host or network device). On many networks,
only a small percentage of IP addresses are active at any given
time. This is particularly common with private address space
such as 10.0.0.0/8. That network has 16 million IPs, but I have
seen it used by companies with less than a thousand machines. Host
discovery can find those machines in a sparsely allocated sea of
@@ -642,6 +642,63 @@ you would expect.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-PY <replaceable>port list</replaceable></option> (SCTP INIT Ping)
<indexterm><primary><option>-PY</option></primary></indexterm>
<indexterm><primary>SCTP INIT ping</primary></indexterm>
</term>
<listitem>
<para>This option sends an SCTP packet containing a minimal
INIT chunk. The default destination port is 80 (configurable
at compile time by changing
<varname>DEFAULT_SCTP_PROBE_PORT_SPEC</varname>
<indexterm><primary><varname>DEFAULT_SCTP_PROBE_PORT_SPEC</varname></primary></indexterm>
in <filename>nmap.h</filename>).
<indexterm><primary><filename>nmap.h</filename></primary></indexterm>
Alternate ports can be specified as a parameter. The syntax
is the same as for the
<option>-p</option> except that port type specifiers like
<literal>S:</literal> are not allowed. Examples are
<option>-PY22</option> and
<option>-PY22,80,179,5060</option>. Note that there
can be no space between <option>-PY</option> and the port
list. If multiple probes are specified they will be sent in
parallel.</para>
<para>The INIT chunk suggests to the remote system that you
are attempting to establish an association. Normally the
destination port will be closed, and an ABORT chunk will be
sent back. If the port happens to be open, the target will
take the second step of an SCTP
four-way-handshake<indexterm><primary>four-way handshake</primary></indexterm>
by responding with an INIT-ACK chunk. If the machine running
Nmap has a functional SCTP stack, then it tears down the
nascent association by responding with an ABORT chunk rather
than sending a COOKIE-ECHO chunk which would be the next step
in the four-way-handshake. The ABORT packet is sent by the
kernel of the machine running Nmap in response to the
unexpected INIT-ACK, not by Nmap itself.</para>
<para>Nmap does not care whether the port is open or closed.
Either the ABORT or INIT-ACK response discussed previously tell
Nmap that the host is available and responsive.</para>
<para>On Unix boxes, only the privileged user
<literal>root</literal><indexterm><primary>privileged users</primary></indexterm>
is generally able to send and receive raw SCTP
packets.<indexterm><primary>raw packets</primary></indexterm>
Using SCTP INIT Pings is currently not possible for unprivileged
users.<indexterm><primary>unprivileged users</primary><secondary>limitations of</secondary></indexterm>
The same limitation applies to IPv6, which is currently not
supported for
SCTP INIT Ping.<indexterm><primary>IPv6</primary><secondary>limitations of</secondary></indexterm>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-PE</option>;
@@ -654,9 +711,9 @@ you would expect.</para>
</term>
<listitem>
<para>In addition to the unusual TCP and UDP host discovery
types discussed previously, Nmap can send the standard
packets sent by the ubiquitous
<para>In addition to the unusual TCP, UDP and SCTP host
discovery types discussed previously, Nmap can send the
standard packets sent by the ubiquitous
<application>ping</application> program. Nmap sends an ICMP
type 8 (echo request) packet to the target IP addresses,
expecting a type 0 (echo reply) in return from available
@@ -709,17 +766,17 @@ you would expect.</para>
which sends IP packets with the specified protocol number
set in their IP header. The protocol list
takes the same format as do port lists in the
previously discussed TCP and UDP host discovery options. If
no protocols are specified, the default is to send multiple
previously discussed TCP, UDP and SCTP host discovery options.
If no protocols are specified, the default is to send multiple
IP packets for ICMP (protocol 1), IGMP (protocol 2), and
IP-in-IP (protocol 4). The default protocols can be
configured at compile-time by changing
<varname>DEFAULT_PROTO_PROBE_PORT_SPEC</varname><indexterm><primary><varname>DEFAULT_PROTO_PROBE_PORT_SPEC</varname></primary></indexterm>
in <filename>nmap.h</filename>.
Note that for the ICMP, IGMP, TCP (protocol 6), and UDP
(protocol 17), the packets are sent with the proper protocol
headers while other protocols are sent with no additional data
beyond the IP header (unless the
Note that for the ICMP, IGMP, TCP (protocol 6), UDP
(protocol 17) and SCTP (protocol 132), the packets are sent
with the proper protocol headers while other protocols are
sent with no additional data beyond the IP header (unless the
<option>--data-length</option> option is specified).</para>
<para>This host discovery method looks for either responses
@@ -899,11 +956,12 @@ options from across the Internet might show that port as <literal>filtered</lite
<indexterm><primary><literal>open</literal> port state</primary></indexterm>
open</term>
<listitem><para>An application is actively accepting TCP
connections or UDP packets on this port. Finding these is often the
primary goal of port scanning. Security-minded people know that
each open port is an avenue for attack. Attackers and pen-testers
want to exploit the open ports, while administrators try to close or
protect them with firewalls without thwarting legitimate users.
connections, UDP datagrams or SCTP associations on this port.
Finding these is often the primary goal of port scanning.
Security-minded people know that each open port is an avenue for attack.
Attackers and pen-testers want to exploit the open ports, while
administrators try to close or protect them with firewalls without
thwarting legitimate users.
Open ports are also interesting for non-security scans because they show
services available for use on the network.
</para></listitem></varlistentry>
@@ -1019,8 +1077,10 @@ discussed in the individual scan type entries.</para>
<para>This section documents the dozen or so port scan
techniques supported by Nmap. Only one method may be used at a time,
except that UDP scan (<option>-sU</option>) may be combined with any
one of the TCP scan types. As a memory aid, port scan type options
except that UDP scan (<option>-sU</option>) and any one of the
SCTP scan types (<option>-sY</option>, <option>-sZ</option>)
may be combined with any one of the TCP scan types.
As a memory aid, port scan type options
are of the form <option>-s<replaceable>C</replaceable></option>, where
<replaceable>C</replaceable> is a prominent character in the scan
name, usually the first. The one exception to this is the deprecated
@@ -1160,6 +1220,44 @@ hosts.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-sY</option> (SCTP INIT scan)
<indexterm><primary><option>-sY</option></primary></indexterm>
<indexterm><primary>SCTP INIT scan</primary></indexterm>
</term>
<listitem>
<para>
<ulink role="hidepdf" url="http://www.rfc-editor.org/rfc/rfc4960.txt">SCTP</ulink>
is a relatively new alternative to the TCP and UDP protocols,
combining most characteristics of TCP and UDP, and also adding
new features like multi-homing and multi-streaming. It is mostly
being used for SS7/SIGTRAN related services but has the potential
to be used for other applications as well.
SCTP INIT scan is the SCTP equivalent of a TCP SYN scan.
It can be performed quickly, scanning thousands of ports per
second on a fast network not hampered by restrictive firewalls.
Like SYN scan, INIT scan is relatively unobtrusive and stealthy,
since it never completes SCTP associations. It also allows clear,
reliable differentiation between the <literal>open</literal>,
<literal>closed</literal>, and <literal>filtered</literal>
states.</para>
<para>This technique is often referred to as half-open scanning,
because you don't open a full SCTP association. You send an INIT
chunk, as if you are going to open a real association and then wait
for a response. An INIT-ACK chunk indicates the port is listening
(open), while an ABORT chunk is indicative of a non-listener. If no
response is received after several retransmissions, the port is
marked as filtered. The port is also marked filtered if an ICMP
unreachable error (type 3, code 1, 2, 3, 9, 10, or 13) is
received.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-sN</option>; <option>-sF</option>; <option>-sX</option> (TCP NULL, FIN, and Xmas scans)
@@ -1349,6 +1447,35 @@ used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-sZ</option> (SCTP COOKIE ECHO scan)
<indexterm><primary><option>-sZ</option></primary></indexterm>
<indexterm><primary>SCTP COOKIE ECHO scan</primary></indexterm>
</term>
<listitem>
<para>
SCTP COOKIE ECHO scan is a more advanced SCTP scan. It takes
advantage of the fact that SCTP implementations should silently
drop packets containing COOKIE ECHO chunks on open ports, but
send an ABORT if the port is closed.
The advantage of this scan type is that it is not as obvious a
port scan than an INIT scan. Also, there may be non-stateful
firewall rulesets blocking INIT chunks, but not COOKIE ECHO
chunks. Don't be fooled into thinking that this will make a
port scan invisible; a good IDS will be able to detect SCTP
COOKIE ECHO scans too.
The downside is that SCTP COOKIE ECHO scans cannot differentiate
between <literal>open</literal> and <literal>filtered</literal>
ports, leaving you with the state <literal>open|filtered</literal>
in both cases.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-sI <replaceable>zombie host</replaceable><optional>:<replaceable>probeport</replaceable></optional></option> (idle scan)
@@ -3148,7 +3275,7 @@ support the option completely, as does UDP scan.</para>
<listitem>
<para>Asks Nmap to use an invalid TCP or UDP checksum for
<para>Asks Nmap to use an invalid TCP, UDP or SCTP checksum for
packets sent to target hosts. Since virtually all
host IP stacks properly drop these packets, any responses received
are likely coming from a firewall or IDS that didn't bother to
@@ -3157,6 +3284,31 @@ support the option completely, as does UDP scan.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--adler32</option> (Use deprecated Adler32 instead of CRC32C for SCTP checksums)
<indexterm><primary><option>--adler32</option></primary></indexterm>
<indexterm><primary>CRC32C checksum</primary></indexterm>
<indexterm><primary>Adler32 checksum</primary></indexterm>
<indexterm><primary>SCTP checksum</primary></indexterm>
<indexterm><primary>checksums</primary></indexterm>
</term>
<listitem>
<para>Asks Nmap to use the deprecated Adler32 algorithm
for calculating the SCTP checksum. If <option>--adler32</option>
is not given, CRC-32C (Castagnoli) is used.
<ulink role="hidepdf" url="http://www.rfc-editor.org/rfc/rfc2960.txt">RFC 2960</ulink>
originally defined Adler32 as checksum algorithm for SCTP;
<ulink role="hidepdf" url="http://www.rfc-editor.org/rfc/rfc4960.txt">RFC 4960</ulink>
later redefined the SCTP checksums to use CRC-32C. Current SCTP
implementations should be using CRC-32C, but in order to elicit
responses from old, legacy SCTP implementations, it may be
preferrable to use Adler32.</para>
</listitem>
</varlistentry>
</variablelist>
<indexterm class="endofrange" startref="man-bypass-ids-indexterm"/>

View File

@@ -97,9 +97,9 @@
class TargetGroup;
class Target;
/* Stores "port info" which is TCP/UDP ports or RPC program ids */
/* Stores "port info" which is TCP/UDP/SCTP ports or RPC program ids */
struct portinfo {
unsigned long portno; /* TCP/UDP port or RPC program id or IP protocool */
unsigned long portno; /* TCP/UDP/SCTP port or RPC program id or IP protocool */
short trynum;
int sd[3]; /* Socket descriptors for connect_scan */
struct timeval sent[3];
@@ -218,10 +218,12 @@ struct scan_lists {
unsigned short *syn_ping_ports;
unsigned short *ack_ping_ports;
unsigned short *udp_ping_ports;
unsigned short *sctp_ping_ports;
unsigned short *proto_ping_ports;
int syn_ping_count;
int ack_ping_count;
int udp_ping_count;
int sctp_ping_count;
int proto_ping_count;
//the above fields are only used for host discovery
//the fields below are only used for port scanning
@@ -229,10 +231,12 @@ struct scan_lists {
int tcp_count;
unsigned short *udp_ports;
int udp_count;
unsigned short *sctp_ports;
int sctp_count;
unsigned short *prots;
int prot_count;
};
typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, 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, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_SCAN, TRACEROUTE, REF_TRACEROUTE}stype;
typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, SCTP_INIT_SCAN, SCTP_COOKIE_ECHO_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_SCAN, TRACEROUTE, REF_TRACEROUTE}stype;
#endif /*GLOBAL_STRUCTURES_H */

View File

@@ -445,9 +445,12 @@ Index: libdnet-stripped/src/intf-win32.c
} else
return (-1);
Added eth_get_pcap_devname() that matches up a dnet name to its pcap
equivalent by matching hardwar addresses. It's similar to the code
used in eth_open()
o Added eth_get_pcap_devname() that matches up a dnet name to its pcap
equivalent by matching hardwar addresses. It's similar to the code
used in eth_open()
o Added SCTP support. Not including patches since the SCTP changes
will be included in the next libdnet release. [Daniel Roethlisberger]
o Handle the case of sa_len == 0 (meaning 0.0.0.0) in addr_stob.
Index: src/addr.c

View File

@@ -19,6 +19,7 @@
#include <dnet/icmp.h>
#include <dnet/tcp.h>
#include <dnet/udp.h>
#include <dnet/sctp.h>
#include <dnet/intf.h>
#include <dnet/route.h>

View File

@@ -5,4 +5,4 @@ include $(top_srcdir)/Makefile.am.common
dnetincludedir = $(includedir)/dnet
dnetinclude_HEADERS = addr.h arp.h blob.h eth.h fw.h icmp.h intf.h ip.h \
ip6.h os.h rand.h route.h tcp.h tun.h udp.h
ip6.h os.h rand.h route.h tcp.h tun.h udp.h sctp.h

View File

@@ -0,0 +1,168 @@
/*
* sctp.h
*
* Stream Control Transmission Protocol (RFC 4960).
*
* Copyright (c) 2008-2009 Daniel Roethlisberger <daniel@roe.ch>
*
* $Id$
*/
#ifndef DNET_SCTP_H
#define DNET_SCTP_H
#define SCTP_HDR_LEN 12
struct sctp_hdr {
uint16_t sh_sport; /* source port */
uint16_t sh_dport; /* destination port */
uint32_t sh_vtag; /* sctp verification tag */
uint32_t sh_sum; /* sctp checksum */
};
#define SCTP_PORT_MAX 65535
#define sctp_pack_hdr(hdr, sport, dport, vtag) do { \
struct sctp_hdr *sctp_pack_p = (struct sctp_hdr *)(hdr); \
sctp_pack_p->sh_sport = htons(sport); \
sctp_pack_p->sh_dport = htons(dport); \
sctp_pack_p->sh_vtag = htonl(vtag); \
} while (0)
struct sctp_chunkhdr {
uint8_t sch_type; /* chunk type */
uint8_t sch_flags; /* chunk flags */
uint16_t sch_length; /* chunk length */
};
/* chunk types */
#define SCTP_DATA 0x00
#define SCTP_INIT 0x01
#define SCTP_INIT_ACK 0x02
#define SCTP_SACK 0x03
#define SCTP_HEARTBEAT 0x04
#define SCTP_HEARTBEAT_ACK 0x05
#define SCTP_ABORT 0x06
#define SCTP_SHUTDOWN 0x07
#define SCTP_SHUTDOWN_ACK 0x08
#define SCTP_ERROR 0x09
#define SCTP_COOKIE_ECHO 0x0a
#define SCTP_COOKIE_ACK 0x0b
#define SCTP_ECNE 0x0c
#define SCTP_CWR 0x0d
#define SCTP_SHUTDOWN_COMPLETE 0x0e
#define SCTP_AUTH 0x0f /* RFC 4895 */
#define SCTP_ASCONF_ACK 0x80 /* RFC 5061 */
#define SCTP_PKTDROP 0x81 /* draft-stewart-sctp-pktdrprep-08 */
#define SCTP_PAD 0x84 /* RFC 4820 */
#define SCTP_FORWARD_TSN 0xc0 /* RFC 3758 */
#define SCTP_ASCONF 0xc1 /* RFC 5061 */
/* chunk types bitmask flags */
#define SCTP_TYPEFLAG_REPORT 1
#define SCTP_TYPEFLAG_SKIP 2
#define sctp_pack_chunkhdr(hdr, type, flags, length) do { \
struct sctp_chunkhdr *sctp_pack_chp = (struct sctp_chunkhdr *)(hdr);\
sctp_pack_chp->sch_type = type; \
sctp_pack_chp->sch_flags = flags; \
sctp_pack_chp->sch_length = htons(length); \
} while (0)
/*
* INIT chunk
*/
struct sctp_chunkhdr_init {
struct sctp_chunkhdr chunkhdr;
uint32_t schi_itag; /* Initiate Tag */
uint32_t schi_arwnd; /* Advertised Receiver Window Credit */
uint16_t schi_nos; /* Number of Outbound Streams */
uint16_t schi_nis; /* Number of Inbound Streams */
uint32_t schi_itsn; /* Initial TSN */
};
#define sctp_pack_chunkhdr_init(hdr, type, flags, length, itag, \
arwnd, nos, nis, itsn) do { \
struct sctp_chunkhdr_init *sctp_pack_chip = \
(struct sctp_chunkhdr_init *)(hdr); \
sctp_pack_chunkhdr(sctp_pack_chip, type, flags, length); \
sctp_pack_chip->schi_itag = htonl(itag); \
sctp_pack_chip->schi_arwnd = htonl(arwnd); \
sctp_pack_chip->schi_nos = htons(nos); \
sctp_pack_chip->schi_nis = htons(nis); \
sctp_pack_chip->schi_itsn = htonl(itsn); \
} while (0)
/*
* INIT ACK chunk
*/
struct sctp_chunkhdr_init_ack {
struct sctp_chunkhdr chunkhdr;
uint32_t schia_itag; /* Initiate Tag */
uint32_t schia_arwnd; /* Advertised Receiver Window Credit */
uint16_t schia_nos; /* Number of Outbound Streams */
uint16_t schia_nis; /* Number of Inbound Streams */
uint32_t schia_itsn; /* Initial TSN */
};
#define sctp_pack_chunkhdr_init_ack(hdr, type, flags, length, itag, \
arwnd, nos, nis, itsn) do { \
struct sctp_chunkhdr_init_ack *sctp_pack_chip = \
(struct sctp_chunkhdr_init_ack *)(hdr); \
sctp_pack_chunkhdr(sctp_pack_chip, type, flags, length); \
sctp_pack_chip->schia_itag = htonl(itag); \
sctp_pack_chip->schia_arwnd = htonl(arwnd); \
sctp_pack_chip->schia_nos = htons(nos); \
sctp_pack_chip->schia_nis = htons(nis); \
sctp_pack_chip->schia_itsn = htonl(itsn); \
} while (0)
/*
* ABORT chunk
*/
struct sctp_chunkhdr_abort {
struct sctp_chunkhdr chunkhdr;
/* empty */
};
#define sctp_pack_chunkhdr_abort(hdr, type, flags, length) do { \
struct sctp_chunkhdr_abort *sctp_pack_chip = \
(struct sctp_chunkhdr_abort *)(hdr); \
sctp_pack_chunkhdr(sctp_pack_chip, type, flags, length); \
} while (0)
/*
* SHUTDOWN ACK chunk
*/
struct sctp_chunkhdr_shutdown_ack {
struct sctp_chunkhdr chunkhdr;
/* empty */
};
#define sctp_pack_chunkhdr_shutdown_ack(hdr, type, flags, length) do { \
struct sctp_chunkhdr_shutdown_ack *sctp_pack_chip = \
(struct sctp_chunkhdr_shutdown_ack *)(hdr); \
sctp_pack_chunkhdr(sctp_pack_chip, type, flags, length); \
} while (0)
/*
* COOKIE ECHO chunk
*/
struct sctp_chunkhdr_cookie_echo {
struct sctp_chunkhdr chunkhdr;
/* empty */
};
#define sctp_pack_chunkhdr_cookie_echo(hdr, type, flags, length) do { \
struct sctp_chunkhdr_cookie_echo *sctp_pack_chip = \
(struct sctp_chunkhdr_cookie_echo *)(hdr); \
sctp_pack_chunkhdr(sctp_pack_chip, type, flags, length); \
} while (0)
#endif /* DNET_SCTP_H */

View File

@@ -270,6 +270,10 @@
RelativePath=".\include\dnet\udp.h"
>
</File>
<File
RelativePath=".\include\dnet\sctp.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"

View File

@@ -0,0 +1,83 @@
/*
* crc32ct.h
*
* Public domain.
*
* $Id$
*/
#ifndef CRC32CT_H
#define CRC32CT_H
#define CRC32C_POLY 0x1EDC6F41
#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
static unsigned long crc_c[256] = {
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
};
#endif /* CRC32CT_H */

View File

@@ -17,6 +17,30 @@
#include <string.h>
#include "dnet.h"
#include "crc32ct.h"
/* CRC-32C (Castagnoli). Public domain. */
static unsigned long
_crc32c(unsigned char *buf, int len)
{
int i;
unsigned long crc32 = ~0L;
unsigned long result;
unsigned char byte0, byte1, byte2, byte3;
for (i = 0; i < len; i++) {
CRC32C(crc32, buf[i]);
}
result = ~crc32;
byte0 = result & 0xff;
byte1 = (result >> 8) & 0xff;
byte2 = (result >> 16) & 0xff;
byte3 = (result >> 24) & 0xff;
crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
return crc32;
}
ssize_t
ip_add_option(void *buf, size_t len, int proto,
@@ -123,6 +147,13 @@ ip_checksum(void *buf, size_t len)
if (!udp->uh_sum)
udp->uh_sum = 0xffff; /* RFC 768 */
}
} else if (ip->ip_p == IP_PROTO_SCTP) {
struct sctp_hdr *sctp = (struct sctp_hdr *)((u_char *)ip + hl);
if (len >= SCTP_HDR_LEN) {
sctp->sh_sum = 0;
sctp->sh_sum = htonl(_crc32c((u_char *)sctp, len));
}
} else if (ip->ip_p == IP_PROTO_ICMP || ip->ip_p == IP_PROTO_IGMP) {
struct icmp_hdr *icmp = (struct icmp_hdr *)((u_char *)ip + hl);

View File

@@ -31,9 +31,11 @@ rje 5/udp 0.000593 # Remote Job Entry
unknown 6/tcp 0.000502
echo 7/tcp 0.004855
echo 7/udp 0.024679
echo 7/sctp 0.000000
unknown 8/tcp 0.000013
discard 9/tcp 0.003764 # sink null
discard 9/udp 0.015733 # sink null
discard 9/sctp 0.000000 # sink null
unknown 10/tcp 0.000063
systat 11/tcp 0.000075 # Active Users
systat 11/udp 0.000577 # Active Users
@@ -50,10 +52,13 @@ chargen 19/tcp 0.002559 # ttytst source Character Generator
chargen 19/udp 0.015865 # ttytst source Character Generator
ftp-data 20/tcp 0.001079 # File Transfer [Default Data]
ftp-data 20/udp 0.001878 # File Transfer [Default Data]
ftp-data 20/sctp 0.000000 # File Transfer [Default Data]
ftp 21/tcp 0.197667 # File Transfer [Control]
ftp 21/udp 0.004844 # File Transfer [Control]
ftp 21/sctp 0.000000 # File Transfer [Control]
ssh 22/tcp 0.182286 # Secure Shell Login
ssh 22/udp 0.003905 # Secure Shell Login
ssh 22/sctp 0.000000 # Secure Shell Login
telnet 23/tcp 0.221265
telnet 23/udp 0.006211
priv-mail 24/tcp 0.001154 # any private mail system
@@ -153,6 +158,7 @@ finger 79/tcp 0.006022
finger 79/udp 0.000956
http 80/tcp 0.484143 # World Wide Web HTTP
http 80/udp 0.035767 # World Wide Web HTTP
http 80/sctp 0.000000 # World Wide Web HTTP
hosts2-ns 81/tcp 0.012056 # HOSTS2 Name Server
hosts2-ns 81/udp 0.001005 # HOSTS2 Name Server
xfer 82/tcp 0.002923 # XFER Utility
@@ -323,6 +329,7 @@ xdmcp 177/udp 0.018551 # X Display Manager Control Protocol
nextstep 178/udp 0.000346 # NextStep Window Server
bgp 179/tcp 0.010538 # Border Gateway Protocol
bgp 179/udp 0.000494 # Border Gateway Protocol
bgp 179/sctp 0.000000 # Border Gateway Protocol
ris 180/tcp 0.000038 # Intergraph
ris 180/udp 0.000478 # Intergraph
unify 181/tcp 0.000025
@@ -660,6 +667,7 @@ cvc_hostd 442/tcp 0.000138
cvc_hostd 442/udp 0.000774
https 443/tcp 0.208669 # secure http (SSL)
https 443/udp 0.010840
https 443/sctp 0.000000
snpp 444/tcp 0.004466 # Simple Network Paging Protocol
snpp 444/udp 0.000873 # Simple Network Paging Protocol
microsoft-ds 445/tcp 0.056944 # SMB directly over IP
@@ -1865,8 +1873,9 @@ unknown 1164/udp 0.000330
unknown 1165/tcp 0.000152
unknown 1166/tcp 0.000152
unknown 1166/udp 0.000330
unknown 1167/tcp 0.000076
phone 1167/udp 0.000593 # conference calling
cisco-ipsla 1167/tcp 0.000076 # Cisco IP SLAs Control Protocol
cisco-ipsla 1167/udp 0.000593 # Cisco IP SLAs Control Protocol
cisco-ipsla 1167/sctp 0.000000 # Cisco IP SLAs Control Protocol
unknown 1168/tcp 0.000076
unknown 1168/udp 0.000330
unknown 1169/tcp 0.000380
@@ -2586,7 +2595,9 @@ unknown 1808/tcp 0.000076
unknown 1811/tcp 0.000076
unknown 1812/tcp 0.000152
radius 1812/udp 0.053839 # RADIUS authentication protocol (RFC 2138)
radius 1812/sctp 0.000000 # RADIUS authentication protocol (RFC 2138)
radacct 1813/udp 0.010429 # RADIUS accounting protocol (RFC 2139)
radacct 1813/sctp 0.000000 # RADIUS accounting protocol (RFC 2139)
unknown 1814/udp 0.000330
unknown 1815/udp 0.000330
unknown 1818/udp 0.000330
@@ -2893,6 +2904,7 @@ unknown 2222/tcp 0.000608
msantipiracy 2222/udp 0.047902 # Microsoft Office OS X antipiracy network monitor
unknown 2223/udp 0.010902
unknown 2224/tcp 0.000076
rcip-itu 2225/sctp 0.000000 # Resource Connection Initiation Protocol
unknown 2226/udp 0.000330
ivs-video 2232/tcp 0.000151 # IVS Video default
ivs-video 2232/udp 0.000626 # IVS Video default
@@ -2998,6 +3010,7 @@ unknown 2417/udp 0.000330
unknown 2418/tcp 0.000076
unknown 2418/udp 0.000330
unknown 2425/tcp 0.000076
mgcp-gateway 2427/sctp 0.000000
unknown 2429/udp 0.000330
venus 2430/tcp 0.000050
venus 2430/udp 0.000478
@@ -3189,7 +3202,9 @@ unknown 2901/udp 0.000330
unknown 2902/tcp 0.000076
extensisportfolio 2903/tcp 0.000100 # Portfolio Server by Extensis Product Group
unknown 2903/udp 0.000330
unknown 2904/udp 0.000330
m2ua 2904/udp 0.000330 # SIGTRAN M2UA
m2ua 2904/sctp 0.000000 # SIGTRAN M2UA
m3ua 2905/sctp 0.000000 # SIGTRAN M3UA
unknown 2908/tcp 0.000076
unknown 2908/udp 0.000661
unknown 2909/tcp 0.000228
@@ -3203,7 +3218,9 @@ unknown 2928/udp 0.000330
unknown 2930/tcp 0.000076
unknown 2932/udp 0.000330
unknown 2940/udp 0.000330
unknown 2944/udp 0.000330
megaco-h248 2944/udp 0.000330 # Megaco H-248 (Text)
megaco-h248 2944/sctp 0.000000 # Megaco H-248 (Text)
h248-binary 2945/sctp 0.000000 # Megaco H-248 (Binary)
wap-push 2948/udp 0.000791 # Windows Mobile devices often have this
unknown 2950/udp 0.000330
unknown 2951/udp 0.000330
@@ -3275,6 +3292,7 @@ unknown 3080/tcp 0.000076
sj3 3086/tcp 0.000050 # SJ3 (kanji input)
unknown 3089/tcp 0.000076
unknown 3094/udp 0.000661
itu-bicc-stc 3097/sctp 0.000000 # ITU-T Q.1902.1/Q.2150.3
unknown 3099/udp 0.000330
unknown 3102/tcp 0.000076
unknown 3102/udp 0.000330
@@ -3488,6 +3506,7 @@ unknown 3544/udp 0.000661
unknown 3546/tcp 0.000304
unknown 3551/tcp 0.000380
unknown 3555/udp 0.000330
m2pa 3565/sctp 0.000000 # M2PA
unknown 3569/udp 0.000991
unknown 3571/udp 0.000330
unknown 3573/udp 0.000330
@@ -3630,8 +3649,11 @@ unknown 3853/tcp 0.000152
unknown 3856/tcp 0.000076
unknown 3859/tcp 0.000152
unknown 3860/tcp 0.000076
unknown 3863/tcp 0.000152
unknown 3868/tcp 0.000076
asap-tcp 3863/tcp 0.000152 # RSerPool ASAP (TCP)
asap-sctp 3863/sctp 0.000000 # RSerPool ASAP (SCTP)
asap-sctp-tls 3864/sctp 0.000000 # RSerPool ASAP/TLS (SCTP)
diameter 3868/tcp 0.000076 # DIAMETER
diameter 3868/sctp 0.000000 # DIAMETER
unknown 3869/tcp 0.000228
unknown 3869/udp 0.000330
unknown 3870/tcp 0.000152
@@ -4048,6 +4070,8 @@ unknown 4712/tcp 0.000076
unknown 4713/udp 0.000330
unknown 4726/udp 0.000330
unknown 4734/udp 0.000330
ipfix 4739/sctp 0.000000 # IP Flow Info Export
ipfixs 4740/sctp 0.000000 # IP Flow Info Export over DTLS
unknown 4741/udp 0.000330
unknown 4743/udp 0.000330
unknown 4745/tcp 0.000076
@@ -4184,8 +4208,10 @@ unknown 5056/udp 0.000330
unknown 5059/udp 0.000330
sip 5060/tcp 0.010613 # Session Initiation Protocol (SIP)
sip 5060/udp 0.044350 # Session Initiation Protocol (SIP)
unknown 5061/tcp 0.000228
unknown 5061/udp 0.000330
sip 5060/sctp 0.000000 # Session Initiation Protocol (SIP)
sip-tls 5061/tcp 0.000228 # SIP-TLS
sip-tls 5061/udp 0.000330 # SIP-TLS
sip-tls 5061/sctp 0.000000 # SIP-TLS
unknown 5063/tcp 0.000152
unknown 5066/tcp 0.000076
unknown 5068/udp 0.000330
@@ -4202,6 +4228,8 @@ unknown 5087/tcp 0.000228
unknown 5088/tcp 0.000076
unknown 5090/tcp 0.000076
unknown 5090/udp 0.000330
car 5090/sctp 0.000000 # Candidate AR
cxtp 5091/sctp 0.000000 # Context Transfer Protocol
unknown 5093/udp 0.003304
unknown 5094/udp 0.000330
unknown 5095/tcp 0.000076
@@ -4435,7 +4463,9 @@ unknown 5665/tcp 0.000076
nrpe 5666/tcp 0.006614 # Nagios NRPE
unknown 5667/tcp 0.000076
unknown 5667/udp 0.000330
unknown 5672/tcp 0.000076
amqp 5672/tcp 0.000076 # AMQP
amqp 5672/sctp 0.000000 # AMQP
v5ua 5675/sctp 0.000000 # V5UA application port
unknown 5678/tcp 0.000228
activesync 5679/tcp 0.000590 # Microsoft ActiveSync PDY synchronization
canna 5680/tcp 0.000151 # Canna (Japanese Input)
@@ -5133,6 +5163,7 @@ unknown 7609/udp 0.000330
unknown 7613/udp 0.000661
unknown 7617/udp 0.000330
unknown 7625/tcp 0.000380
simco 7626/sctp 0.000000 # SImple Middlebox COnfiguration (SIMCO)
unknown 7627/tcp 0.000380
unknown 7628/tcp 0.000076
unknown 7630/udp 0.000330
@@ -5432,8 +5463,9 @@ unknown 8455/udp 0.000330
unknown 8458/udp 0.000330
unknown 8468/udp 0.000330
unknown 8470/tcp 0.000076
unknown 8471/tcp 0.000076
unknown 8471/udp 0.000330
pim-port 8471/tcp 0.000076 # PIM over Reliable Transport
pim-port 8471/udp 0.000330 # PIM over Reliable Transport
pim-port 8471/sctp 0.000000 # PIM over Reliable Transport
unknown 8472/tcp 0.000076
unknown 8473/udp 0.000330
unknown 8474/tcp 0.000076
@@ -5624,7 +5656,8 @@ unknown 9079/udp 0.000661
unknown 9080/tcp 0.000380
unknown 9080/udp 0.000330
unknown 9081/tcp 0.000228
unknown 9084/tcp 0.000076
aurora 9084/tcp 0.000076 # IBM AURORA Performance Visualizer
aurora 9084/sctp 0.000000 # IBM AURORA Performance Visualizer
unknown 9085/udp 0.000330
unknown 9086/udp 0.000330
unknown 9088/udp 0.000330
@@ -5890,8 +5923,12 @@ unknown 9893/udp 0.000330
unknown 9894/udp 0.000330
unknown 9897/udp 0.000661
unknown 9898/tcp 0.000228
unknown 9900/tcp 0.000380
sctp-tunneling 9899/sctp 0.000000 # SCTP Tunneling
iua 9900/tcp 0.000380 # IUA
iua 9900/sctp 0.000000 # IUA
unknown 9901/tcp 0.000076
enrp-sctp 9901/sctp 0.000000 # ENRP server channel
enrp-sctp-tls 9902/sctp 0.000000 # ENRP/TLS server channel
unknown 9908/tcp 0.000076
unknown 9909/tcp 0.000076
unknown 9910/tcp 0.000076
@@ -6367,8 +6404,11 @@ unknown 11982/udp 0.000330
unknown 11988/udp 0.000330
unknown 11991/udp 0.000330
unknown 11997/udp 0.000330
wmereceiving 11997/sctp 0.000000 # WorldMailExpress
unknown 11998/udp 0.000330
wmedistribution 11998/sctp 0.000000 # WorldMailExpress
unknown 11999/udp 0.000330
wmereporting 11999/sctp 0.000000 # WorldMailExpress
cce4x 12000/tcp 0.000427 # ClearCommerce Engine 4.x (www.clearcommerce.com)
unknown 12000/udp 0.000661
unknown 12001/tcp 0.000076
@@ -6807,7 +6847,8 @@ unknown 13989/udp 0.000330
unknown 13992/udp 0.000330
unknown 13996/udp 0.000330
unknown 14000/tcp 0.000380
unknown 14001/tcp 0.000076
sua 14001/tcp 0.000076 # SUA
sua 14001/sctp 0.000000 # SUA
unknown 14006/udp 0.000330
unknown 14034/udp 0.000330
unknown 14035/udp 0.000330
@@ -8369,6 +8410,7 @@ unknown 20039/udp 0.000654
unknown 20041/udp 0.000654
unknown 20045/udp 0.000654
unknown 20048/udp 0.000654
nfsrdma 20049/sctp 0.000000 # Network File System (NFS) over RDMA
unknown 20052/tcp 0.000076
unknown 20055/udp 0.000654
unknown 20056/udp 0.000654

78
nmap.cc
View File

@@ -216,7 +216,7 @@ printf("%s %s ( %s )\n"
" -sL: List Scan - simply list targets to scan\n"
" -sP: Ping Scan - go no further than determining if host is online\n"
" -PN: Treat all hosts as online -- skip host discovery\n"
" -PS/PA/PU[portlist]: TCP SYN/ACK or UDP discovery to given ports\n"
" -PS/PA/PU/PY[portlist]: TCP SYN/ACK, UDP or SCTP discovery to given ports\n"
" -PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes\n"
" -PO[protocol list]: IP Protocol Ping\n"
" -n/-R: Never do DNS resolution/Always resolve [default: sometimes]\n"
@@ -229,6 +229,7 @@ printf("%s %s ( %s )\n"
" -sN/sF/sX: TCP Null, FIN, and Xmas scans\n"
" --scanflags <flags>: Customize TCP scan flags\n"
" -sI <zombie host[:probeport]>: Idle scan\n"
" -sY/sZ: SCTP INIT/COOKIE-ECHO scans\n"
" -sO: IP protocol scan\n"
" -b <FTP relay host>: FTP bounce scan\n"
"PORT SPECIFICATION AND SCAN ORDER:\n"
@@ -280,7 +281,8 @@ printf("%s %s ( %s )\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"
" --badsum: Send packets with a bogus TCP/UDP/SCTP checksum\n"
" --adler32: Use deprecated Adler32 instead of CRC32C for SCTP checksums\n"
"OUTPUT:\n"
" -oN/-oX/-oS/-oG <file>: Output scan in normal, XML, s|<rIpt kIddi3,\n"
" and Grepable format, respectively, to the given filename.\n"
@@ -673,6 +675,7 @@ int nmap_main(int argc, char *argv[]) {
{"min-rate", required_argument, 0, 0},
{"max_rate", required_argument, 0, 0},
{"max-rate", required_argument, 0, 0},
{"adler32", no_argument, 0, 0},
{"stats_every", required_argument, 0, 0},
{"stats-every", required_argument, 0, 0},
{0, 0, 0, 0}
@@ -936,6 +939,8 @@ int nmap_main(int argc, char *argv[]) {
} else if(optcmp(long_options[option_index].name, "max-rate") == 0) {
if (sscanf(optarg, "%f", &o.max_packet_send_rate) != 1 || o.max_packet_send_rate <= 0.0)
fatal("Argument to --max-rate must be a positive floating-point number");
} else if (optcmp(long_options[option_index].name, "adler32") == 0) {
o.adler32 = true;
} else if(optcmp(long_options[option_index].name, "stats-every") == 0) {
l = tval2msecs(optarg);
if (l < 0) fatal("Argument to --stats-every cannot be negative.");
@@ -1120,6 +1125,19 @@ int nmap_main(int argc, char *argv[]) {
assert(ports.udp_ping_count > 0);
}
}
else if (*optarg == 'Y') {
if (ports.sctp_ping_count > 0)
fatal("Only one -PY option is allowed. Combine port ranges with commas.");
o.pingtype |= (PINGTYPE_SCTP_INIT);
if (*(optarg + 1) != '\0') {
getpts_simple(optarg + 1, SCAN_SCTP_PORT, &ports.sctp_ping_ports, &ports.sctp_ping_count);
if (ports.sctp_ping_count <= 0)
fatal("Bogus argument to -PY: %s", optarg + 1);
} else {
getpts_simple(DEFAULT_SCTP_PROBE_PORT_SPEC, SCAN_SCTP_PORT, &ports.sctp_ping_ports, &ports.sctp_ping_count);
assert(ports.sctp_ping_count > 0);
}
}
else if (*optarg == 'B') {
if (ports.ack_ping_count > 0)
fatal("Only one -PB, -PA, or -PT option is allowed. Combine port ranges with commas.");
@@ -1193,6 +1211,8 @@ int nmap_main(int argc, char *argv[]) {
case 'V': o.servicescan = 1; break;
case 'W': o.windowscan = 1; break;
case 'X': o.xmasscan++; break;
case 'Y': o.sctpinitscan = 1; break;
case 'Z': o.sctpcookieechoscan = 1; break;
default: error("Scantype %c not supported\n",*p); printusage(argv[0], -1); break;
}
p++;
@@ -1220,6 +1240,7 @@ int nmap_main(int argc, char *argv[]) {
o.setMaxRttTimeout(1250);
o.setInitialRttTimeout(500);
o.setMaxTCPScanDelay(10);
o.setMaxSCTPScanDelay(10);
o.setMaxRetransmissions(6);
} else if (*optarg == '5' || (strcasecmp(optarg, "Insane") == 0)) {
o.timing_level = 5;
@@ -1228,6 +1249,7 @@ int nmap_main(int argc, char *argv[]) {
o.setInitialRttTimeout(250);
o.host_timeout = 900000;
o.setMaxTCPScanDelay(5);
o.setMaxSCTPScanDelay(5);
o.setMaxRetransmissions(2);
} else {
fatal("Unknown timing mode (-T argument). Use either \"Paranoid\", \"Sneaky\", \"Polite\", \"Normal\", \"Aggressive\", \"Insane\" or a number from 0 (Paranoid) to 5 (Insane)");
@@ -1259,6 +1281,7 @@ int nmap_main(int argc, char *argv[]) {
o.scan_delay = pre_scan_delay;
if (o.scan_delay > o.maxTCPScanDelay()) o.setMaxTCPScanDelay(o.scan_delay);
if (o.scan_delay > o.maxUDPScanDelay()) o.setMaxUDPScanDelay(o.scan_delay);
if (o.scan_delay > o.maxSCTPScanDelay()) o.setMaxSCTPScanDelay(o.scan_delay);
o.max_parallelism = 1;
if(pre_max_parallelism != -1)
fatal("You can't use --max-parallelism with --scan-delay.");
@@ -1266,6 +1289,7 @@ int nmap_main(int argc, char *argv[]) {
if (pre_max_scan_delay != -1) {
o.setMaxTCPScanDelay(pre_max_scan_delay);
o.setMaxUDPScanDelay(pre_max_scan_delay);
o.setMaxSCTPScanDelay(pre_max_scan_delay);
}
if (pre_init_rtt_timeout != -1) o.setInitialRttTimeout(pre_init_rtt_timeout);
if (pre_min_rtt_timeout != -1) o.setMinRttTimeout(pre_min_rtt_timeout);
@@ -1360,7 +1384,7 @@ int nmap_main(int argc, char *argv[]) {
}
// Uncomment the following line to use the common lisp port spec test suite
//printf("port spec: (%d %d %d)\n", ports.tcp_count, ports.udp_count, ports.prot_count); exit(0);
//printf("port spec: (%d %d %d %d)\n", ports.tcp_count, ports.udp_count, ports.stcp_count, ports.prot_count); exit(0);
#ifdef WIN32
if (o.sendpref & PACKET_SEND_IP) {
@@ -1421,6 +1445,8 @@ int nmap_main(int argc, char *argv[]) {
*/
if ((o.TCPScan()) && ports.tcp_count == 0)
error("WARNING: a TCP scan type was requested, but no tcp ports were specified. Skipping this scan type.");
if (o.SCTPScan() && ports.sctp_count == 0)
error("WARNING: a SCTP scan type was requested, but no sctp ports were specified. Skipping this scan type.");
if (o.UDPScan() && ports.udp_count == 0)
error("WARNING: UDP scan was requested, but no udp ports were specified. Skipping this scan type.");
if (o.ipprotscan && ports.prot_count == 0)
@@ -1517,7 +1543,7 @@ int nmap_main(int argc, char *argv[]) {
/* Before we randomize the ports scanned, lets output them to machine
parseable output */
if (o.verbose)
output_ports_to_machine_parseable_output(&ports, o.TCPScan(), o.udpscan, o.ipprotscan);
output_ports_to_machine_parseable_output(&ports, o.TCPScan(), o.UDPScan(), o.SCTPScan(), o.ipprotscan);
/* more fakeargv junk, BTW malloc'ing extra space in argv[0] doesn't work */
if (quashargv) {
@@ -1547,7 +1573,7 @@ int nmap_main(int argc, char *argv[]) {
log_write(LOG_PLAIN, "--------------- Timing report ---------------\n");
log_write(LOG_PLAIN, " hostgroups: min %d, max %d\n", o.minHostGroupSz(), o.maxHostGroupSz());
log_write(LOG_PLAIN, " rtt-timeouts: init %d, min %d, max %d\n", o.initialRttTimeout(), o.minRttTimeout(), o.maxRttTimeout());
log_write(LOG_PLAIN, " max-scan-delay: TCP %d, UDP %d\n", o.maxTCPScanDelay(), o.maxUDPScanDelay());
log_write(LOG_PLAIN, " max-scan-delay: TCP %d, UDP %d, SCTP %d\n", o.maxTCPScanDelay(), o.maxUDPScanDelay(), o.maxSCTPScanDelay());
log_write(LOG_PLAIN, " parallelism: min %d, max %d\n", o.min_parallelism, o.max_parallelism);
log_write(LOG_PLAIN, " max-retries: %d, host-timeout: %ld\n", o.getMaxRetransmissions(), o.host_timeout);
log_write(LOG_PLAIN, " min-rate: %g, max-rate: %g\n", o.min_packet_send_rate, o.max_packet_send_rate);
@@ -1561,6 +1587,8 @@ int nmap_main(int argc, char *argv[]) {
PortList::initializePortMap(IPPROTO_TCP, ports.tcp_ports, ports.tcp_count);
if (o.UDPScan())
PortList::initializePortMap(IPPROTO_UDP, ports.udp_ports, ports.udp_count);
if (o.SCTPScan())
PortList::initializePortMap(IPPROTO_SCTP, ports.sctp_ports, ports.sctp_count);
if (randomize) {
if (ports.tcp_count) {
@@ -1570,6 +1598,8 @@ int nmap_main(int argc, char *argv[]) {
}
if (ports.udp_count)
shortfry(ports.udp_ports, ports.udp_count);
if (ports.sctp_count)
shortfry(ports.sctp_ports, ports.sctp_count);
if (ports.prot_count)
shortfry(ports.prots, ports.prot_count);
}
@@ -1776,6 +1806,12 @@ int nmap_main(int argc, char *argv[]) {
if (o.connectscan)
ultra_scan(Targets, &ports, CONNECT_SCAN);
if (o.sctpinitscan)
ultra_scan(Targets, &ports, SCTP_INIT_SCAN);
if (o.sctpcookieechoscan)
ultra_scan(Targets, &ports, SCTP_COOKIE_ECHO_SCAN);
if (o.ipprotscan)
ultra_scan(Targets, &ports, IPPROT_SCAN);
@@ -2136,12 +2172,14 @@ void getpts(const char *origexpr, struct scan_lists *ports) {
u8 *porttbl;
int range_type = 0;
int portwarning = 0;
int i, tcpi, udpi, proti;
int i, tcpi, udpi, sctpi, proti;
if (o.TCPScan())
range_type |= SCAN_TCP_PORT;
if (o.UDPScan())
range_type |= SCAN_UDP_PORT;
if (o.SCTPScan())
range_type |= SCAN_SCTP_PORT;
if (o.ipprotscan)
range_type |= SCAN_PROTOCOLS;
@@ -2150,22 +2188,25 @@ void getpts(const char *origexpr, struct scan_lists *ports) {
getpts_aux(origexpr, // Pass on the expression
0, // Don't start off nested
porttbl, // Our allocated port table
range_type, // Defaults to TCP/UDP/Protos
range_type, // Defaults to TCP/UDP/SCTP/Protos
&portwarning); // No, we haven't warned them about dup ports yet
ports->tcp_count = 0;
ports->udp_count = 0;
ports->sctp_count = 0;
ports->prot_count = 0;
for(i = 0; i <= 65535; i++) {
if (porttbl[i] & SCAN_TCP_PORT)
ports->tcp_count++;
if (porttbl[i] & SCAN_UDP_PORT)
ports->udp_count++;
if (porttbl[i] & SCAN_SCTP_PORT)
ports->sctp_count++;
if (porttbl[i] & SCAN_PROTOCOLS && i < 256)
ports->prot_count++;
}
if (range_type != 0 && 0 == (ports->tcp_count + ports->udp_count + ports->prot_count))
if (range_type != 0 && 0 == (ports->tcp_count + ports->udp_count + ports->sctp_count + ports->prot_count))
fatal("No ports specified -- If you really don't want to scan any ports use ping scan...");
if (ports->tcp_count) {
@@ -2174,15 +2215,20 @@ void getpts(const char *origexpr, struct scan_lists *ports) {
if (ports->udp_count) {
ports->udp_ports = (unsigned short *)safe_zalloc(ports->udp_count * sizeof(unsigned short));
}
if (ports->sctp_count) {
ports->sctp_ports = (unsigned short *)safe_zalloc(ports->sctp_count * sizeof(unsigned short));
}
if (ports->prot_count) {
ports->prots = (unsigned short *)safe_zalloc(ports->prot_count * sizeof(unsigned short));
}
for(i=tcpi=udpi=proti=0; i <= 65535; i++) {
for(i=tcpi=udpi=sctpi=proti=0; i <= 65535; i++) {
if (porttbl[i] & SCAN_TCP_PORT)
ports->tcp_ports[tcpi++] = i;
if (porttbl[i] & SCAN_UDP_PORT)
ports->udp_ports[udpi++] = i;
if (porttbl[i] & SCAN_SCTP_PORT)
ports->sctp_ports[sctpi++] = i;
if (porttbl[i] & SCAN_PROTOCOLS && i < 256)
ports->prots[proti++] = i;
}
@@ -2192,7 +2238,7 @@ void getpts(const char *origexpr, struct scan_lists *ports) {
/* This function is like getpts except it only allocates space for and stores
values into one unsigned short array, instead of an entire scan_lists struct
For that reason, T:, U:, and P: restrictions are not allowed and only one
For that reason, T:, U:, S: and P: restrictions are not allowed and only one
bit in range_type may be set. */
void getpts_simple(const char *origexpr, int range_type,
unsigned short **list, int *count) {
@@ -2264,6 +2310,11 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_
range_type = SCAN_UDP_PORT;
continue;
}
if (*current_range == 'S' && *++current_range == ':') {
current_range++;
range_type = SCAN_SCTP_PORT;
continue;
}
if (*current_range == 'P' && *++current_range == ':') {
current_range++;
range_type = SCAN_PROTOCOLS;
@@ -2381,6 +2432,10 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_
nmap_getservbyport(htons(rangestart), "udp")) {
porttbl[rangestart] |= SCAN_UDP_PORT;
}
if ((range_type & SCAN_SCTP_PORT) &&
nmap_getservbyport(htons(rangestart), "sctp")) {
porttbl[rangestart] |= SCAN_SCTP_PORT;
}
if ((range_type & SCAN_PROTOCOLS) &&
nmap_getprotbynum(htons(rangestart))) {
porttbl[rangestart] |= SCAN_PROTOCOLS;
@@ -2412,6 +2467,7 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_
void free_scan_lists(struct scan_lists *ports) {
if (ports->tcp_ports) free(ports->tcp_ports);
if (ports->udp_ports) free(ports->udp_ports);
if (ports->sctp_ports) free(ports->sctp_ports);
if (ports->prots) free(ports->prots);
if (ports->syn_ping_ports) free(ports->syn_ping_ports);
if (ports->ack_ping_ports) free(ports->ack_ping_ports);
@@ -2513,6 +2569,8 @@ const char *scantype2str(stype scantype) {
case CONNECT_SCAN: return "Connect Scan"; break;
case NULL_SCAN: return "NULL Scan"; break;
case WINDOW_SCAN: return "Window Scan"; break;
case SCTP_INIT_SCAN: return "SCTP INIT Scan"; break;
case SCTP_COOKIE_ECHO_SCAN: return "SCTP COOKIE-ECHO Scan"; break;
case RPC_SCAN: return "RPCGrind Scan"; break;
case MAIMON_SCAN: return "Maimon Scan"; break;
case IPPROT_SCAN: return "IPProto Scan"; break;

13
nmap.h
View File

@@ -218,6 +218,11 @@ void *realloc();
#include <arpa/inet.h>
#endif
/* For systems without SCTP in netinet/in.h, such as MacOS X */
#ifndef IPPROTO_SCTP
#define IPPROTO_SCTP 132
#endif
/* Keep assert() defined for security reasons */
#undef NDEBUG
@@ -271,6 +276,9 @@ void *realloc();
change this to 113 */
#define DEFAULT_UDP_PROBE_PORT_SPEC "31338" /* The port UDP ping probes go to
if unspecified by user */
#define DEFAULT_SCTP_PROBE_PORT_SPEC "80" /* The port SCTP probes go to
if unspecified by
user */
#define DEFAULT_PROTO_PROBE_PORT_SPEC "1,2,4" /* The IPProto ping probes to use
if unspecified by user */
@@ -290,6 +298,10 @@ void *realloc();
#define MAX_UDP_SCAN_DELAY 1000
#endif
#ifndef MAX_SCTP_SCAN_DELAY
#define MAX_SCTP_SCAN_DELAY 1000
#endif
/* Maximum number of extra hostnames, OSs, and devices, we
consider when outputing the extra service info fields */
#define MAX_SERVICE_INFO_FIELDS 5
@@ -339,6 +351,7 @@ void *realloc();
#define PINGTYPE_UDP 512
#define PINGTYPE_ARP 1024
#define PINGTYPE_PROTO 2048
#define PINGTYPE_SCTP_INIT 4096
/* Empirically determined optimum combinations of different numbers of probes:
-PE

View File

@@ -81,7 +81,8 @@ static int ports (lua_State *L)
Port *current = NULL;
lua_newtable(L);
for (int i = 0; states[i] != PORT_HIGHEST_STATE; i++)
while ((current = plist->nextPort(current, TCPANDUDP, states[i])) != NULL)
while ((current = plist->nextPort(current, TCPANDUDPANDSCTP,
states[i])) != NULL)
{
lua_newtable(L);
set_portinfo(L, current);

View File

@@ -14,6 +14,7 @@ extern "C" {
#include "nmap_rpc.h"
#include "nmap_dns.h"
#include "osscan.h"
#include "protocols.h"
/* #include "output.h" UNNECESSARY?? */
@@ -115,7 +116,7 @@ void set_portinfo(lua_State *L, Port* port) {
lua_pushstring(L, sd.name);
lua_setfield(L, -2, "service");
lua_pushstring(L, (port->proto == IPPROTO_TCP)? "tcp": "udp");
lua_pushstring(L, IPPROTO2STR(port->proto));
lua_setfield(L, -2, "protocol");
lua_newtable(L);
@@ -353,7 +354,8 @@ Port *get_port (lua_State *L, Target *target, int index)
portno = (int) lua_tointeger(L, -2);
protocol = strcmp(lua_tostring(L, -1), "tcp") == 0 ? IPPROTO_TCP :
strcmp(lua_tostring(L, -1), "udp") == 0 ? IPPROTO_UDP :
luaL_error(L, "port 'protocol' field must be \"udp\" or \"tcp\"");
strcmp(lua_tostring(L, -1), "sctp") == 0 ? IPPROTO_SCTP :
luaL_error(L, "port 'protocol' field must be \"udp\", \"sctp\" or \"tcp\"");
while ((port = target->ports.nextPort(port, protocol, PORT_UNKNOWN)) != NULL)
if (port->portno == portno)
break;

View File

@@ -20,6 +20,7 @@ extern "C"
#include "NmapOps.h"
#include "utils.h"
#include "tcpip.h"
#include "protocols.h"
#if HAVE_OPENSSL
# include <openssl/ssl.h>
@@ -754,9 +755,7 @@ void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *yield)
void l_nsock_trace(nsock_iod nsiod, const char *message, int direction)
{
int status;
int protocol;
int af;
struct sockaddr local;
@@ -773,7 +772,7 @@ void l_nsock_trace(nsock_iod nsiod, const char *message, int direction)
&local, &remote, sizeof(sockaddr));
log_write(LOG_STDOUT, "%s: %s %s:%d %s %s:%d | %s\n",
SCRIPT_ENGINE,
(protocol == IPPROTO_TCP) ? "TCP" : "UDP",
IPPROTO2STR_UC(protocol),
inet_ntop_both(af, &local, ipstring_local),
inet_port_both(af, &local),
(direction == TO) ? ">" : "<",

View File

@@ -509,7 +509,7 @@ static char* formatScriptOutput(ScriptResult sr) {
output and the XML output. It is pretty ugly -- in particular I
should write helper functions to handle the table creation */
void printportoutput(Target *currenths, PortList *plist) {
char protocol[4];
char protocol[MAX_IPPROTOSTRLEN+1];
char rpcinfo[64];
char rpcmachineinfo[64];
char portinfo[64];
@@ -701,11 +701,11 @@ void printportoutput(Target *currenths, PortList *plist) {
}
} else {
current = NULL;
while( (current=plist->nextPort(current, TCPANDUDP, 0))!=NULL ) {
while( (current=plist->nextPort(current, TCPANDUDPANDSCTP, 0))!=NULL ) {
if (!plist->isIgnoredState(current->state)) {
if (!first) log_write(LOG_MACHINE,", ");
else first = 0;
strcpy(protocol,(current->proto == IPPROTO_TCP)? "tcp": "udp");
strcpy(protocol, IPPROTO2STR(current->proto));
Snprintf(portinfo, sizeof(portinfo), "%d/%s", current->portno, protocol);
state = statenum2str(current->state);
current->getServiceDeductions(&sd);
@@ -1205,9 +1205,10 @@ char outpbuf[128];
in sequential order for space savings and easier to read output */
void output_ports_to_machine_parseable_output(struct scan_lists *ports,
int tcpscan, int udpscan,
int protscan) {
int sctpscan, int protscan) {
int tcpportsscanned = ports->tcp_count;
int udpportsscanned = ports->udp_count;
int sctpportsscanned = ports->sctp_count;
int protsscanned = ports->prot_count;
log_write(LOG_MACHINE, "# Ports scanned: TCP(%d;", tcpportsscanned);
if (tcpportsscanned)
@@ -1215,6 +1216,9 @@ void output_ports_to_machine_parseable_output(struct scan_lists *ports,
log_write(LOG_MACHINE, ") UDP(%d;", udpportsscanned);
if (udpportsscanned)
output_rangelist_given_ports(LOG_MACHINE, ports->udp_ports, udpportsscanned);
log_write(LOG_MACHINE, ") SCTP(%d;", sctpportsscanned);
if (sctpportsscanned)
output_rangelist_given_ports(LOG_MACHINE, ports->sctp_ports, sctpportsscanned);
log_write(LOG_MACHINE, ") PROTOCOLS(%d;", protsscanned);
if (protsscanned)
output_rangelist_given_ports(LOG_MACHINE, ports->prots, protsscanned);
@@ -1279,6 +1283,10 @@ void output_xml_scaninfo_records(struct scan_lists *scanlist) {
doscaninfo("fin", "tcp", scanlist->tcp_ports, scanlist->tcp_count);
if (o.udpscan)
doscaninfo("udp", "udp", scanlist->udp_ports, scanlist->udp_count);
if (o.sctpinitscan)
doscaninfo("sctpinit", "sctp", scanlist->sctp_ports, scanlist->sctp_count);
if (o.sctpcookieechoscan)
doscaninfo("sctpcookieecho", "sctp", scanlist->sctp_ports, scanlist->sctp_count);
if (o.ipprotscan)
doscaninfo("ipproto", "ip", scanlist->prots, scanlist->prot_count);
log_flush_all();
@@ -1782,7 +1790,7 @@ void printserviceinfooutput(Target *currenths) {
for (i=0; i<MAX_SERVICE_INFO_FIELDS; i++)
hostname_tbl[i][0] = ostype_tbl[i][0] = devicetype_tbl[i][0] = '\0';
while ((p = currenths->ports.nextPort(p, TCPANDUDP, PORT_OPEN))) {
while ((p = currenths->ports.nextPort(p, TCPANDUDPANDSCTP, PORT_OPEN))) {
// The following 2 lines (from portlist.h) tell us that we don't
// need to worry about free()ing anything in the serviceDeductions struct.
// pass in an allocated struct serviceDeductions (don't wory about initializing, and

View File

@@ -171,7 +171,7 @@ int log_open(int logt, int append, char *filename);
in sequential order for space savings and easier to read output */
void output_ports_to_machine_parseable_output(struct scan_lists *ports,
int tcpscan, int udpscan,
int protscan);
int sctpscan, int protscan);
/* Similar to output_ports_to_machine_parseable_output, this function
outputs the XML version, which is scaninfo records of each scan

View File

@@ -95,6 +95,7 @@
#include "nmap.h"
#include "NmapOps.h"
#include "services.h"
#include "protocols.h"
#include "nmap_rpc.h"
#include "tcpip.h"
@@ -257,7 +258,7 @@ int Port::getServiceDeductions(struct serviceDeductions *sd) {
populateFullVersionString(sd);
return 0;
} else if (serviceprobe_results == PROBESTATE_EXCLUDED) {
service = nmap_getservbyport(htons(portno), (proto == IPPROTO_TCP)? "tcp" : "udp");
service = nmap_getservbyport(htons(portno), IPPROTO2STR(proto));
if (service) sd->name = service->s_name;
@@ -274,7 +275,7 @@ int Port::getServiceDeductions(struct serviceDeductions *sd) {
}
// So much for service detection or RPC. Maybe we can find it in the file
service = nmap_getservbyport(htons(portno), (proto == IPPROTO_TCP)? "tcp" : "udp");
service = nmap_getservbyport(htons(portno), IPPROTO2STR(proto));
if (service) {
sd->dtype = SERVICE_DETECTION_TABLE;
sd->name = service->s_name;
@@ -388,6 +389,7 @@ void Port::setRPCProbeResults(int rpcs, unsigned long rpcp,
#define INPROTO2PORTLISTPROTO(p) \
((p)==IPPROTO_TCP ? PORTLIST_PROTO_TCP : \
(p)==IPPROTO_UDP ? PORTLIST_PROTO_UDP : \
(p)==IPPROTO_SCTP ? PORTLIST_PROTO_SCTP : \
PORTLIST_PROTO_IP)
@@ -540,12 +542,12 @@ int PortList::getStateCounts(int state){
first "afterthisport". Then supply the most recent returned port
for each subsequent call. When no more matching ports remain, NULL
will be returned. To restrict returned ports to just one protocol,
specify IPPROTO_TCP or IPPROTO_UDP for allowed_protocol. A TCPANDUDP
for allowed_protocol matches either. A 0 for allowed_state matches
all possible states. This function returns ports in numeric
order from lowest to highest, except that if you ask for both TCP &
UDP, every TCP port will be returned before we start returning UDP
ports */
specify IPPROTO_TCP, IPPROTO_UDP or IPPROTO_SCTP for
allowed_protocol. A TCPANDUDPANDSCTP for allowed_protocol matches
either. A 0 for allowed_state matches all possible states. This
function returns ports in numeric order from lowest to highest,
except that if you ask for both TCP, UDP & SCTP, every TCP port
will be returned before we start returning UDP and SCTP ports */
Port *PortList::nextPort(Port *afterthisport,
int allowed_protocol, int allowed_state) {
int proto;
@@ -559,8 +561,10 @@ Port *PortList::nextPort(Port *afterthisport,
mapped_pno = port_map[proto][afterthisport->portno];
mapped_pno++; // we're interested in next port after current
}else { // running for the first time
if(allowed_protocol == TCPANDUDP) // if both protocols, then first search TCP
if (allowed_protocol == TCPANDUDPANDSCTP)
proto = INPROTO2PORTLISTPROTO(IPPROTO_TCP);
else if (allowed_protocol == UDPANDSCTP)
proto = INPROTO2PORTLISTPROTO(IPPROTO_UDP);
else
proto = INPROTO2PORTLISTPROTO(allowed_protocol);
mapped_pno = 0;
@@ -574,9 +578,15 @@ Port *PortList::nextPort(Port *afterthisport,
}
}
/* if all protocols, than after TCP search UDP */
if(allowed_protocol == TCPANDUDP && proto == INPROTO2PORTLISTPROTO(IPPROTO_TCP))
return(nextPort(NULL, IPPROTO_UDP, allowed_state));
/* if all protocols, than after TCP search UDP & SCTP */
if((!afterthisport && allowed_protocol == TCPANDUDPANDSCTP) ||
(afterthisport && proto == INPROTO2PORTLISTPROTO(IPPROTO_TCP)))
return(nextPort(NULL, UDPANDSCTP, allowed_state));
/* if all protocols, than after UDP search SCTP */
if((!afterthisport && allowed_protocol == UDPANDSCTP) ||
(afterthisport && proto == INPROTO2PORTLISTPROTO(IPPROTO_UDP)))
return(nextPort(NULL, IPPROTO_SCTP, allowed_state));
return(NULL);
}

View File

@@ -113,7 +113,8 @@
#define PORT_HIGHEST_STATE 9 /* ***IMPORTANT -- BUMP THIS UP WHEN STATES ARE
ADDED *** */
#define TCPANDUDP IPPROTO_MAX
#define TCPANDUDPANDSCTP IPPROTO_MAX
#define UDPANDSCTP (IPPROTO_MAX + 1)
#define CONF_NONE 0
#define CONF_LOW 1
@@ -254,8 +255,9 @@ class Port {
enum portlist_proto { // PortList Protocols
PORTLIST_PROTO_TCP = 0,
PORTLIST_PROTO_UDP = 1,
PORTLIST_PROTO_IP = 2,
PORTLIST_PROTO_MAX = 3
PORTLIST_PROTO_SCTP = 2,
PORTLIST_PROTO_IP = 3,
PORTLIST_PROTO_MAX = 4
};
class PortList {
@@ -281,12 +283,12 @@ class PortList {
first "afterthisport". Then supply the most recent returned port
for each subsequent call. When no more matching ports remain, NULL
will be returned. To restrict returned ports to just one protocol,
specify IPPROTO_TCP or IPPROTO_UDP for allowed_protocol. A TCPANDUDP
for allowed_protocol matches either. A 0 for allowed_state matches
all possible states. This function returns ports in numeric
order from lowest to highest, except that if you ask for both TCP &
UDP, every TCP port will be returned before we start returning UDP
ports */
specify IPPROTO_TCP, IPPROTO_UDP or UPPROTO_SCTP for
allowed_protocol. A TCPANDUDPANDSCTP for allowed_protocol matches
either. A 0 for allowed_state matches all possible states. This
function returns ports in numeric order from lowest to highest,
except that if you ask for TCP, UDP & SCTP, all TCP ports will be
returned before we start returning UDP and finally SCTP ports */
Port *nextPort(Port *afterthisport,
int allowed_protocol, int allowed_state);

View File

@@ -113,7 +113,8 @@ const char *reason_text[ER_MAX+1]={
"unknown", "admin-prohibited", "unknown", "time-exceeded", "unknown", "unknown",
"timestamp-reply", "unknown", "unknown", "unknown", "addressmask-reply",
"no-ipid-change", "ipid-change", "arp-response", "tcp-response",
"no-response", "localhost-response", "script-set", "unknown-response","user-set"
"no-response", "init-ack", "abort",
"localhost-response", "script-set", "unknown-response","user-set"
};
const char *reason_pl_text[ER_MAX+1]={
@@ -125,7 +126,8 @@ const char *reason_pl_text[ER_MAX+1]={
"unknowns", "admin-prohibiteds", "unknowns", "time-exceededs", "unknowns",
"unknowns", "timestamp-replies", "unknowns", "unknowns", "unknowns",
"addressmask-replies", "no-ipid-changes", "ipid-changes", "arp-responses",
"tcp-responses", "no-responses", "localhost-response", "script-set", "unknown-responses"
"tcp-responses", "no-responses", "init-acks", "aborts",
"localhost-response", "script-set", "unknown-responses"
};
static void state_reason_summary_init(state_reason_summary_t *r) {
@@ -246,7 +248,7 @@ static unsigned int get_state_summary(state_reason_summary_t *head, PortList *Po
Port *current = NULL;
state_reason_summary_t *reason;
unsigned int total = 0;
unsigned short proto = (o.ipprotscan) ? IPPROTO_IP : TCPANDUDP;
unsigned short proto = (o.ipprotscan) ? IPPROTO_IP : TCPANDUDPANDSCTP;
if(head == NULL)
return 0;

View File

@@ -139,7 +139,8 @@ enum reason_codes {
ER_ADDRESSMASKREPLY=29, ER_NOIPIDCHANGE, ER_IPIDCHANGE,
ER_ARPRESPONSE, ER_TCPRESPONSE, ER_NORESPONSE,
ER_LOCALHOST, ER_SCRIPT, ER_UNKNOWN, ER_USER, ER_MAX=ER_USER /* 39 */
ER_INITACK, ER_ABORT,
ER_LOCALHOST, ER_SCRIPT, ER_UNKNOWN, ER_USER, ER_MAX=ER_USER /* 41 */
};
/* Be careful to update these values if any ICMP

View File

@@ -111,4 +111,16 @@ struct protocol_list {
int addprotocolsfromservmask(char *mask, u8 *porttbl);
struct protoent *nmap_getprotbynum(int num);
#define MAX_IPPROTOSTRLEN 4
#define IPPROTO2STR(p) \
((p)==IPPROTO_TCP ? "tcp" : \
(p)==IPPROTO_UDP ? "udp" : \
(p)==IPPROTO_SCTP ? "sctp" : \
"n/a")
#define IPPROTO2STR_UC(p) \
((p)==IPPROTO_TCP ? "TCP" : \
(p)==IPPROTO_UDP ? "UDP" : \
(p)==IPPROTO_SCTP ? "SCTP" : \
"N/A")
#endif

View File

@@ -170,6 +170,8 @@ static const char *pspectype2ascii(int type) {
return "TCP";
case PS_UDP:
return "UDP";
case PS_SCTP:
return "SCTP";
case PS_PROTO:
return "IP Proto";
case PS_ICMP:
@@ -200,11 +202,16 @@ struct IPExtraProbeData_udp {
u16 sport;
};
struct IPExtraProbeData_sctp {
u16 sport;
};
struct IPExtraProbeData {
u16 ipid; /* host byte order */
union {
struct IPExtraProbeData_tcp tcp;
struct IPExtraProbeData_udp udp;
struct IPExtraProbeData_sctp sctp;
} pd;
};
@@ -227,12 +234,36 @@ public:
/* Pass an arp packet, including ethernet header. Must be 42bytes */
void setARP(u8 *arppkt, u32 arplen);
// The 4 accessors below all return in HOST BYTE ORDER
// source port used if TCP or UDP
// source port used if TCP, UDP or SCTP
u16 sport() {
return (mypspec.proto == IPPROTO_TCP)? probes.IP.pd.tcp.sport : probes.IP.pd.udp.sport; }
// destination port used if TCP or UDP
u16 dport() {
return (mypspec.proto == IPPROTO_TCP)? mypspec.pd.tcp.dport : mypspec.pd.udp.dport; }
switch (mypspec.proto) {
case IPPROTO_TCP:
return probes.IP.pd.tcp.sport;
case IPPROTO_UDP:
return probes.IP.pd.udp.sport;
case IPPROTO_SCTP:
return probes.IP.pd.sctp.sport;
default:
return 0;
}
/* not reached */
}
// destination port used if TCP, UDP or SCTP
u16 dport() {
switch (mypspec.proto) {
case IPPROTO_TCP:
return mypspec.pd.tcp.dport;
case IPPROTO_UDP:
return mypspec.pd.udp.dport;
case IPPROTO_SCTP:
return mypspec.pd.sctp.dport;
default:
/* dport() can get called for other protos if we
* get ICMP responses during IP proto scans. */
return 0;
}
/* not reached */
}
u16 ipid() { return probes.IP.ipid; }
u32 tcpseq(); // TCP sequence number if protocol is TCP
/* Number, such as IPPROTO_TCP, IPPROTO_UDP, etc. */
@@ -395,6 +426,9 @@ public:
/* The index of the next UDP port in o.ping_udpprobes to probe during ping
scan. */
int next_udpportpingidx;
/* The index of the next SCTP port in o.ping_protoprobes to probe during ping
scan. */
int next_sctpportpingidx;
/* The index of the next IP protocol in o.ping_protoprobes to probe during ping
scan. */
int next_protoportpingidx;
@@ -574,6 +608,7 @@ public:
stype scantype;
bool tcp_scan; /* scantype is a type of TCP scan */
bool udp_scan;
bool sctp_scan; /* scantype is a type of SCTP scan */
bool prot_scan;
bool ping_scan; /* Includes trad. ping scan & arp scan */
bool ping_scan_arp; /* ONLY includes arp ping scan */
@@ -667,7 +702,7 @@ static void init_ultra_timing_vals(ultra_timing_vals *timing,
struct ultra_scan_performance_vars *perf,
struct timeval *now);
/* Take a buffer, buf, of size bufsz (32 bytes is sufficient) and
/* Take a buffer, buf, of size bufsz (64 bytes is sufficient) and
writes a short description of the probe (arg1) into buf. It also returns
buf. */
static char *probespec2ascii(const probespec *pspec, char *buf, unsigned int bufsz) {
@@ -694,6 +729,20 @@ static char *probespec2ascii(const probespec *pspec, char *buf, unsigned int buf
case PS_UDP:
Snprintf(buf, bufsz, "udp to port %hu", pspec->pd.udp.dport);
break;
case PS_SCTP:
switch (pspec->pd.sctp.chunktype) {
case SCTP_INIT:
Strncpy(flagbuf, "INIT", sizeof(flagbuf));
break;
case SCTP_COOKIE_ECHO:
Strncpy(flagbuf, "COOKIE-ECHO", sizeof(flagbuf));
break;
default:
Strncpy(flagbuf, "(unknown)", sizeof(flagbuf));
}
Snprintf(buf, bufsz, "sctp to port %hu; chunk: %s", pspec->pd.sctp.dport,
flagbuf);
break;
case PS_PROTO:
Snprintf(buf, bufsz, "protocol %u", (unsigned int) pspec->proto);
break;
@@ -755,6 +804,7 @@ void UltraProbe::setIP(u8 *ippacket, u32 iplen, const probespec *pspec) {
struct ip *ipv4 = (struct ip *) ippacket;
struct tcp_hdr *tcp = NULL;
struct udp_hdr *udp = NULL;
struct sctp_hdr *sctp = NULL;
type = UP_IP;
if (ipv4->ip_v != 4)
@@ -772,6 +822,10 @@ void UltraProbe::setIP(u8 *ippacket, u32 iplen, const probespec *pspec) {
assert(iplen >= (unsigned) ipv4->ip_hl * 4 + 8);
udp = (struct udp_hdr *) ((u8 *) ipv4 + ipv4->ip_hl * 4);
probes.IP.pd.udp.sport = ntohs(udp->uh_sport);
} else if (ipv4->ip_p == IPPROTO_SCTP) {
assert(iplen >= (unsigned) ipv4->ip_hl * 4 + 12);
sctp = (struct sctp_hdr *) ((u8 *) ipv4 + ipv4->ip_hl * 4);
probes.IP.pd.sctp.sport = ntohs(sctp->sh_sport);
}
mypspec = *pspec;
@@ -1022,9 +1076,11 @@ static bool pingprobe_is_appropriate(const UltraScanInfo *USI,
return USI->scantype == CONNECT_SCAN || (USI->ping_scan && USI->ptech.connecttcpscan);
case(PS_TCP):
case(PS_UDP):
case(PS_SCTP):
return (USI->tcp_scan && USI->scantype != CONNECT_SCAN) ||
USI->udp_scan ||
(USI->ping_scan && (USI->ptech.rawtcpscan || USI->ptech.rawudpscan));
USI->sctp_scan ||
(USI->ping_scan && (USI->ptech.rawtcpscan || USI->ptech.rawudpscan || USI->ptech.rawsctpscan));
case(PS_PROTO):
return USI->prot_scan || (USI->ping_scan && USI->ptech.rawprotoscan);
case(PS_ICMP):
@@ -1043,6 +1099,7 @@ static int scantype_no_response_means(stype scantype) {
case ACK_SCAN:
case WINDOW_SCAN:
case CONNECT_SCAN:
case SCTP_INIT_SCAN:
return PORT_FILTERED;
case UDP_SCAN:
case IPPROT_SCAN:
@@ -1050,6 +1107,7 @@ static int scantype_no_response_means(stype scantype) {
case FIN_SCAN:
case MAIMON_SCAN:
case XMAS_SCAN:
case SCTP_COOKIE_ECHO_SCAN:
return PORT_OPENFILTERED;
case PING_SCAN:
case PING_SCAN_ARP:
@@ -1068,6 +1126,7 @@ HostScanStats::HostScanStats(Target *t, UltraScanInfo *UltraSI) {
next_ackportpingidx = 0;
next_synportpingidx = 0;
next_udpportpingidx = 0;
next_sctpportpingidx = 0;
next_protoportpingidx = 0;
sent_icmp_ping = false;
sent_icmp_mask = false;
@@ -1342,8 +1401,9 @@ UltraScanInfo::~UltraScanInfo() {
Basically, any scan type except pure TCP connect scans are raw. */
bool UltraScanInfo::isRawScan() {
return scantype != CONNECT_SCAN
&& (tcp_scan || udp_scan || prot_scan || ping_scan_arp
|| (ping_scan && (ptech.rawicmpscan || ptech.rawtcpscan || ptech.rawudpscan || ptech.rawprotoscan)));
&& (tcp_scan || udp_scan || sctp_scan || prot_scan || ping_scan_arp
|| (ping_scan && (ptech.rawicmpscan || ptech.rawtcpscan || ptech.rawudpscan
|| ptech.rawsctpscan || ptech.rawprotoscan)));
}
/* A circular buffer of the incompleteHosts. nextIncompleteHost() gives
@@ -1439,8 +1499,8 @@ void UltraScanInfo::Init(vector<Target *> &Targets, struct scan_lists *pts, styp
scantype = scantp;
SPM = new ScanProgressMeter(scantype2str(scantype));
send_rate_meter.start(&now);
tcp_scan = udp_scan = prot_scan = ping_scan = noresp_open_scan = false;
ping_scan_arp = false;
tcp_scan = udp_scan = sctp_scan = prot_scan = false;
ping_scan = noresp_open_scan = ping_scan_arp = false;
memset((char *) &ptech, 0, sizeof(ptech));
switch(scantype) {
case FIN_SCAN:
@@ -1458,6 +1518,10 @@ void UltraScanInfo::Init(vector<Target *> &Targets, struct scan_lists *pts, styp
noresp_open_scan = true;
udp_scan = true;
break;
case SCTP_INIT_SCAN:
case SCTP_COOKIE_ECHO_SCAN:
sctp_scan = true;
break;
case IPPROT_SCAN:
noresp_open_scan = true;
prot_scan = true;
@@ -1469,6 +1533,8 @@ void UltraScanInfo::Init(vector<Target *> &Targets, struct scan_lists *pts, styp
ptech.rawicmpscan = 1;
if (o.pingtype & PINGTYPE_UDP)
ptech.rawudpscan = 1;
if (o.pingtype & PINGTYPE_SCTP_INIT)
ptech.rawsctpscan = 1;
if (o.pingtype & PINGTYPE_TCP) {
if (o.isr00t && o.af() == AF_INET)
ptech.rawtcpscan = 1;
@@ -1554,6 +1620,8 @@ unsigned int UltraScanInfo::numProbesPerHost()
numprobes = ports->tcp_count;
} else if (udp_scan) {
numprobes = ports->udp_count;
} else if (sctp_scan) {
numprobes = ports->sctp_count;
} else if (prot_scan) {
numprobes = ports->prot_count;
} else if (ping_scan_arp) {
@@ -1568,6 +1636,8 @@ unsigned int UltraScanInfo::numProbesPerHost()
}
if (ptech.rawudpscan)
numprobes += ports->udp_ping_count;
if (ptech.rawsctpscan)
numprobes += ports->sctp_ping_count;
if (ptech.rawicmpscan) {
if (o.pingtype & PINGTYPE_ICMP_PING)
numprobes++;
@@ -1755,7 +1825,7 @@ int UltraScanInfo::removeCompletedHosts() {
hss->target->targetipstr(), num_outstanding_probes,
num_outstanding_probes == 1 ? "probe" : "probes");
if (o.debugging > 3) {
char tmpbuf[32];
char tmpbuf[64];
std::list<UltraProbe *>::iterator iter;
for (iter = hss->probes_outstanding.begin(); iter != hss->probes_outstanding.end(); iter++)
log_write(LOG_PLAIN, "* %s\n", probespec2ascii((probespec *) (*iter)->pspec(), tmpbuf, sizeof(tmpbuf)));
@@ -1796,6 +1866,8 @@ int determineScanGroupSize(int hosts_scanned_so_far,
if (o.UDPScan())
groupsize = 128;
else if (o.SCTPScan())
groupsize = 128;
else if (o.TCPScan()) {
groupsize = MAX(1024 / (ports->tcp_count ? ports->tcp_count : 1), 64);
if (ports->tcp_count > 1000 && o.timing_level <= 4) {
@@ -1877,7 +1949,23 @@ static int get_next_target_probe(UltraScanInfo *USI, HostScanStats *hss,
pspec->type = PS_UDP;
pspec->proto = IPPROTO_UDP;
pspec->pd.udp.dport = USI->ports->udp_ports[hss->next_portidx++];
return 0;
} else if (USI->sctp_scan) {
if (hss->next_portidx >= USI->ports->sctp_count)
return -1;
pspec->type = PS_SCTP;
pspec->proto = IPPROTO_SCTP;
pspec->pd.sctp.dport = USI->ports->sctp_ports[hss->next_portidx++];
switch (USI->scantype) {
case SCTP_INIT_SCAN:
pspec->pd.sctp.chunktype = SCTP_INIT;
break;
case SCTP_COOKIE_ECHO_SCAN:
pspec->pd.sctp.chunktype = SCTP_COOKIE_ECHO;
break;
default:
assert(0);
}
return 0;
} else if (USI->prot_scan) {
if (hss->next_portidx >= USI->ports->prot_count)
@@ -1922,6 +2010,13 @@ static int get_next_target_probe(UltraScanInfo *USI, HostScanStats *hss,
return 0;
}
}
if (USI->ptech.rawsctpscan && hss->next_sctpportpingidx < USI->ports->sctp_ping_count) {
pspec->type = PS_SCTP;
pspec->proto = IPPROTO_SCTP;
pspec->pd.sctp.dport = USI->ports->sctp_ping_ports[hss->next_sctpportpingidx++];
pspec->pd.sctp.chunktype = SCTP_INIT;
return 0;
}
if (USI->ptech.rawicmpscan) {
pspec->type = PS_ICMP;
pspec->proto = IPPROTO_ICMP;
@@ -1971,6 +2066,10 @@ int HostScanStats::freshPortsLeft() {
if (next_portidx >= USI->ports->udp_count)
return 0;
return USI->ports->udp_count - next_portidx;
} else if (USI->sctp_scan) {
if (next_portidx >= USI->ports->sctp_count)
return 0;
return USI->ports->sctp_count - next_portidx;
} else if (USI->prot_scan) {
if (next_portidx >= USI->ports->prot_count)
return 0;
@@ -1990,6 +2089,8 @@ int HostScanStats::freshPortsLeft() {
}
if (USI->ptech.rawudpscan && next_udpportpingidx < USI->ports->udp_ping_count)
num_probes += USI->ports->udp_ping_count - next_udpportpingidx;
if (USI->ptech.rawsctpscan && next_sctpportpingidx < USI->ports->sctp_ping_count)
num_probes += USI->ports->sctp_ping_count - next_sctpportpingidx;
if (USI->ptech.rawicmpscan) {
if ((o.pingtype & PINGTYPE_ICMP_PING) && !sent_icmp_ping)
num_probes++;
@@ -2337,16 +2438,16 @@ void HostScanStats::getTiming(struct ultra_timing_vals *tmng) {
/* Define a score for a ping probe, for the purposes of deciding whether one
probe should be preferred to another. The order, from most preferred to least
preferred, is
Raw TCP (not filtered, not SYN to an open port)
Raw TCP/SCTP (not filtered, not SYN/INIT to an open port)
ICMP information queries (echo request, timestamp request, netmask req)
ARP
Raw TCP (SYN to an open port)
UDP, IP protocol, or other ICMP (including filtered TCP)
Raw TCP/SCTP (SYN/INIT to an open port)
UDP, IP protocol, or other ICMP (including filtered TCP/SCTP)
TCP connect
Anything else
Raw TCP SYN to an open port is given a low preference because of the risk of
SYN flooding (this is the only case where the port state is considered). The
probe passed to this function is assumed to have received a positive
Raw TCP SYN / SCTP INIT to an open port is given a low preference because of the
risk of SYN flooding (this is the only case where the port state is considered).
The probe passed to this function is assumed to have received a positive
response, that is, it should not have set a port state just by timing out. */
static unsigned int pingprobe_score(const probespec *pspec, int state) {
unsigned int score;
@@ -2360,6 +2461,14 @@ static unsigned int pingprobe_score(const probespec *pspec, int state) {
else
score = 6;
break;
case PS_SCTP:
if (state == PORT_FILTERED) /* Received an ICMP error. */
score = 2;
else if (state == PORT_OPEN || state == PORT_UNKNOWN)
score = 3;
else
score = 6;
break;
case PS_ICMP:
if(pspec->pd.icmp.type==ICMP_ECHO || pspec->pd.icmp.type==ICMP_MASK || pspec->pd.icmp.type==ICMP_TSTAMP)
score = 5;
@@ -2418,6 +2527,9 @@ static bool ultrascan_port_pspec_update(UltraScanInfo *USI,
} else if (pspec->type == PS_UDP) {
proto = IPPROTO_UDP;
portno = pspec->pd.udp.dport;
} else if (pspec->type == PS_SCTP) {
proto = IPPROTO_SCTP;
portno = pspec->pd.sctp.dport;
} else assert(0);
/* First figure out the current state */
@@ -2492,7 +2604,9 @@ double HostScanStats::cc_scale() {
/* Boost the scan delay for this host, usually because too many packet
drops were detected. */
void HostScanStats::boostScanDelay() {
unsigned int maxAllowed = (USI->tcp_scan)? o.maxTCPScanDelay() : o.maxUDPScanDelay();
unsigned int maxAllowed = USI->tcp_scan ? o.maxTCPScanDelay() :
USI->udp_scan ? o.maxUDPScanDelay() :
o.maxSCTPScanDelay();
if (sdn.delayms == 0)
sdn.delayms = (USI->udp_scan)? 50 : 5; // In many cases, a pcap wait takes a minimum of 80ms, so this matters little :(
else sdn.delayms = MIN(sdn.delayms * 2, MAX(sdn.delayms, 1000));
@@ -2640,7 +2754,7 @@ static void ultrascan_host_probe_update(UltraScanInfo *USI, HostScanStats *hss,
if (rcvdtime != NULL && adjust_ping
&& pingprobe_is_better(probe->pspec(), PORT_UNKNOWN, &hss->target->pingprobe, hss->target->pingprobe_state)) {
if (o.debugging > 1) {
char buf[32];
char buf[64];
probespec2ascii(probe->pspec(), buf, sizeof(buf));
log_write(LOG_PLAIN, "Changing ping technique for %s to %s\n", hss->target->targetipstr(), buf);
}
@@ -2727,7 +2841,7 @@ static void ultrascan_port_probe_update(UltraScanInfo *USI, HostScanStats *hss,
if (rcvdtime != NULL && adjust_ping
&& pingprobe_is_better(probe->pspec(), newstate, &hss->target->pingprobe, hss->target->pingprobe_state)) {
if (o.debugging > 1) {
char buf[32];
char buf[64];
probespec2ascii(probe->pspec(), buf, sizeof(buf));
log_write(LOG_PLAIN, "Changing ping technique for %s to %s\n", hss->target->targetipstr(), buf);
}
@@ -2922,6 +3036,9 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
struct eth_nfo *ethptr = NULL;
u8 *tcpops = NULL;
u16 tcpopslen = 0;
u32 vtag = 0;
char *chunk = NULL;
int chunklen = 0;
if (USI->ethsd) {
memcpy(eth.srcmac, hss->target->SrcMACAddress(), 6);
@@ -2984,6 +3101,45 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
send_ip_packet(USI->rawsd, ethptr, packet, packetlen);
free(packet);
}
} else if (pspec->type == PS_SCTP) {
switch (pspec->pd.sctp.chunktype) {
case SCTP_INIT:
chunklen = sizeof(struct sctp_chunkhdr_init);
chunk = (char*)safe_malloc(chunklen);
sctp_pack_chunkhdr_init(chunk, SCTP_INIT, 0, chunklen,
get_random_u32()/*itag*/,
32768, 10, 2048,
get_random_u32()/*itsn*/);
vtag = 0;
break;
case SCTP_COOKIE_ECHO:
chunklen = sizeof(struct sctp_chunkhdr_cookie_echo) + 4;
chunk = (char*)safe_malloc(chunklen);
*((u32*)((char*)chunk + sizeof(struct sctp_chunkhdr_cookie_echo))) =
get_random_u32();
sctp_pack_chunkhdr_cookie_echo(chunk, SCTP_COOKIE_ECHO, 0, chunklen);
vtag = get_random_u32();
break;
default:
assert(0);
}
for(decoy = 0; decoy < o.numdecoys; decoy++) {
packet = build_sctp_raw(&o.decoys[decoy], hss->target->v4hostip(),
o.ttl, ipid, IP_TOS_DEFAULT, false,
o.ipoptions, o.ipoptionslen,
sport, pspec->pd.sctp.dport,
vtag, chunk, chunklen,
o.extra_payload, o.extra_payload_length,
&packetlen);
if (decoy == o.decoyturn) {
probe->setIP(packet, packetlen, pspec);
probe->sent = USI->now;
}
hss->probeSent(packetlen);
send_ip_packet(USI->rawsd, ethptr, packet, packetlen);
free(packet);
}
free(chunk);
} else if (pspec->type == PS_PROTO) {
for(decoy = 0; decoy < o.numdecoys; decoy++) {
switch(pspec->proto) {
@@ -3022,6 +3178,24 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
o.extra_payload, o.extra_payload_length,
&packetlen);
break;
case IPPROTO_SCTP:
{
struct sctp_chunkhdr_init chunk;
sctp_pack_chunkhdr_init(&chunk, SCTP_INIT, 0,
sizeof(struct sctp_chunkhdr_init),
get_random_u32()/*itag*/,
32768, 10, 2048,
get_random_u32()/*itsn*/);
packet = build_sctp_raw(&o.decoys[decoy], hss->target->v4hostip(),
o.ttl, ipid, IP_TOS_DEFAULT, false,
o.ipoptions, o.ipoptionslen,
sport, o.magic_port,
0UL, (char*)&chunk,
sizeof(struct sctp_chunkhdr_init),
o.extra_payload, o.extra_payload_length,
&packetlen);
}
break;
default:
packet = build_ip_raw(&o.decoys[decoy], hss->target->v4hostip(),
@@ -3087,7 +3261,8 @@ static void sendNextScanProbe(UltraScanInfo *USI, HostScanStats *hss) {
else if (pspec.type == PS_CONNECTTCP)
sendConnectScanProbe(USI, hss, pspec.pd.tcp.dport, 0, 0);
else if (pspec.type == PS_TCP || pspec.type == PS_UDP
|| pspec.type == PS_PROTO || pspec.type == PS_ICMP)
|| pspec.type == PS_SCTP || pspec.type == PS_PROTO
|| pspec.type == PS_ICMP)
sendIPScanProbe(USI, hss, &pspec, 0, 0);
else
assert(0);
@@ -3164,7 +3339,7 @@ static void doAnyRetryStackRetransmits(UltraScanInfo *USI) {
available */
static void sendPingProbe(UltraScanInfo *USI, HostScanStats *hss) {
if (o.debugging > 1) {
char tmpbuf[32];
char tmpbuf[64];
log_write(LOG_PLAIN, "Ultrascan PING SENT to %s [%s]\n", hss->target->targetipstr(),
probespec2ascii(&hss->target->pingprobe, tmpbuf, sizeof(tmpbuf)));
}
@@ -3172,7 +3347,8 @@ static void sendPingProbe(UltraScanInfo *USI, HostScanStats *hss) {
sendConnectScanProbe(USI, hss, hss->target->pingprobe.pd.tcp.dport, 0,
hss->nextPingSeq(true));
} else if (hss->target->pingprobe.type == PS_TCP || hss->target->pingprobe.type == PS_UDP
|| hss->target->pingprobe.type == PS_PROTO || hss->target->pingprobe.type == PS_ICMP) {
|| hss->target->pingprobe.type == PS_SCTP || hss->target->pingprobe.type == PS_PROTO
|| hss->target->pingprobe.type == PS_ICMP) {
sendIPScanProbe(USI, hss, &hss->target->pingprobe, 0, hss->nextPingSeq(true));
} else if (hss->target->pingprobe.type == PS_ARP) {
sendArpScanProbe(USI, hss, 0, hss->nextPingSeq(true));
@@ -3191,7 +3367,7 @@ static void sendGlobalPingProbe(UltraScanInfo *USI) {
assert(hss != NULL);
if (o.debugging > 1) {
char tmpbuf[32];
char tmpbuf[64];
log_write(LOG_PLAIN, "Ultrascan GLOBAL PING SENT to %s [%s]\n", hss->target->targetipstr(),
probespec2ascii(&hss->target->pingprobe, tmpbuf, sizeof(tmpbuf)));
}
@@ -3248,6 +3424,9 @@ static void retransmitProbe(UltraScanInfo *USI, HostScanStats *hss,
} else if (probe->protocol() == IPPROTO_UDP) {
newProbe = sendIPScanProbe(USI, hss, probe->pspec(), probe->tryno + 1,
0);
} else if (probe->protocol() == IPPROTO_SCTP) {
newProbe = sendIPScanProbe(USI, hss, probe->pspec(), probe->tryno + 1,
0);
} else if (probe->protocol() == IPPROTO_ICMP) {
newProbe = sendIPScanProbe(USI, hss, probe->pspec(), probe->tryno + 1,
0);
@@ -3910,6 +4089,73 @@ static bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
}
}
goodone = true;
}
} else if (ip->ip_p == IPPROTO_SCTP && !USI->prot_scan) {
struct sctp_hdr *sctp = (struct sctp_hdr *) ((u8 *) ip + ip->ip_hl * 4);
struct sctp_chunkhdr *chunk = (struct sctp_chunkhdr *) ((u8 *) sctp + 12);
/* Now ensure this host is even in the incomplete list */
memset(&sin, 0, sizeof(sin));
sin.sin_addr.s_addr = ip->ip_src.s_addr;
sin.sin_family = AF_INET;
hss = USI->findHost((struct sockaddr_storage *) &sin);
if (!hss) continue; // Not from a host that interests us
setTargetMACIfAvailable(hss->target, &linkhdr, ip, 0);
probeI = hss->probes_outstanding.end();
listsz = hss->num_probes_outstanding();
goodone = false;
/* Find the probe that provoked this response. */
for (probenum = 0; probenum < listsz && !goodone; probenum++) {
probeI--;
probe = *probeI;
if (o.af() != AF_INET || probe->protocol() != IPPROTO_SCTP)
continue;
/* Ensure the connection info matches. */
if (probe->dport() != ntohs(sctp->sh_sport)
|| probe->sport() != ntohs(sctp->sh_dport)
|| hss->target->v4sourceip()->s_addr != ip->ip_dst.s_addr)
continue;
/* Sometimes we get false results when scanning localhost with
-p- because we scan localhost with src port = dst port and
see our outgoing packet and think it is a response. */
if (probe->dport() == probe->sport() &&
ip->ip_src.s_addr == ip->ip_dst.s_addr &&
probe->ipid() == ntohs(ip->ip_id))
continue; /* We saw the packet we ourselves sent */
if (!probe->isPing()) {
/* Now that response has been matched to a probe, I interpret it */
if (USI->scantype == SCTP_INIT_SCAN) {
if (chunk->sch_type == SCTP_INIT_ACK) {
newstate = PORT_OPEN;
current_reason = ER_INITACK;
} else if (chunk->sch_type == SCTP_ABORT) {
newstate = PORT_CLOSED;
current_reason = ER_ABORT;
} else {
if (o.debugging)
error("Received response with unexpected SCTP chunks: %02x",
chunk->sch_type);
break;
}
} else if (USI->scantype == SCTP_COOKIE_ECHO_SCAN) {
if (chunk->sch_type == SCTP_ABORT) {
newstate = PORT_CLOSED;
current_reason = ER_ABORT;
} else {
if (o.debugging)
error("Received response with unexpected SCTP chunks: %02x",
chunk->sch_type);
break;
}
}
}
goodone = true;
}
} else if (ip->ip_p == IPPROTO_ICMP) {
@@ -3922,8 +4168,10 @@ static bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
requiredbytes = /* IPlen*/ 4 * ip->ip_hl +
/* ICMPLen */ 8 +
/* IP2 Len */ 4 * ip2->ip_hl;
if (USI->tcp_scan || USI->udp_scan)
requiredbytes += 8; /* UDP hdr, or TCP hdr up to seq # */
if (USI->tcp_scan || USI->udp_scan || USI->sctp_scan) {
/* UDP hdr, or TCP hdr up to seq #, or SCTP hdr up to vtag */
requiredbytes += 8;
}
/* prot scan has no headers coming back, so we don't reserve the
8 xtra bytes */
if (bytes < requiredbytes) {
@@ -3939,6 +4187,9 @@ static bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
if (USI->udp_scan && ip2->ip_p != IPPROTO_UDP)
continue;
if (USI->sctp_scan && ip2->ip_p != IPPROTO_SCTP)
continue;
/* ensure this packet relates to a packet to the host
we are scanning ... */
memset(&sin, 0, sizeof(sin));
@@ -3969,9 +4220,14 @@ static bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
ntohs(tcp->th_dport) != probe->dport() ||
ntohl(tcp->th_seq) != probe->tcpseq())
continue;
} else if (ip2->ip_p == IPPROTO_SCTP && !USI->prot_scan) {
struct sctp_hdr *sctp = (struct sctp_hdr *) ((u8 *) ip2 + ip2->ip_hl * 4);
if (ntohs(sctp->sh_sport) != probe->sport() ||
ntohs(sctp->sh_dport) != probe->dport())
continue;
} else if (ip2->ip_p == IPPROTO_UDP && !USI->prot_scan) {
/* TODO: IPID verification */
struct udp_hdr *udp = (struct udp_hdr *) ((u8 *) ip2 + ip->ip_hl * 4);
struct udp_hdr *udp = (struct udp_hdr *) ((u8 *) ip2 + ip2->ip_hl * 4);
if (ntohs(udp->uh_sport) != probe->sport() ||
ntohs(udp->uh_dport) != probe->dport())
continue;
@@ -4382,9 +4638,55 @@ static int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
/* Did we fail to find a probe? */
if (probenum >= listsz)
continue;
} else if (ip2->ip_p == IPPROTO_SCTP && USI->ptech.rawsctpscan) {
/* The response was based our SCTP probe */
if ((unsigned) ip2->ip_hl * 4 + 8 > bytes)
continue;
struct sctp_hdr *sctp = (struct sctp_hdr *) ((u8 *) ip2 + ip2->ip_hl * 4);
/* Search for this host on the incomplete list */
memset(&sin, 0, sizeof(sin));
sin.sin_addr.s_addr = ip2->ip_dst.s_addr;
sin.sin_family = AF_INET;
hss = USI->findHost((struct sockaddr_storage *) &sin);
if (!hss) continue; // Not referring to a host that interests us
setTargetMACIfAvailable(hss->target, &linkhdr, ip, 0);
probeI = hss->probes_outstanding.end();
listsz = hss->num_probes_outstanding();
for(probenum = 0; probenum < listsz; probenum++) {
probeI--;
probe = *probeI;
if (o.af() != AF_INET || probe->protocol() != IPPROTO_SCTP)
continue;
if (!allow_ipid_match(probe->ipid(), ntohs(ip2->ip_id)))
continue;
/* Ensure the connection info matches. */
if (probe->dport() != ntohs(sctp->sh_dport) ||
probe->sport() != ntohs(sctp->sh_sport) ||
hss->target->v4sourceip()->s_addr != ip->ip_dst.s_addr)
continue;
/* Sometimes we get false results when scanning localhost with
-p- because we scan localhost with src port = dst port and
see our outgoing packet and think it is a response. */
if (probe->dport() == probe->sport() &&
ip->ip_src.s_addr == ip->ip_dst.s_addr &&
probe->ipid() == ntohs(ip->ip_id))
continue; /* We saw the packet we ourselves sent */
/* If we made it this far, we found it. We don't yet know if it's
going to change a host state (goodone) or not. */
break;
}
/* Did we fail to find a probe? */
if (probenum >= listsz)
continue;
} else if (!USI->ptech.rawprotoscan) {
if (o.debugging)
error("Got ICMP response to a packet which was not TCP, UDP, or ICMP");
error("Got ICMP response to a packet which was not TCP, UDP, SCTP or ICMP");
continue;
}
@@ -4575,6 +4877,52 @@ static int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) {
if (o.debugging)
log_write(LOG_STDOUT, "In response to UDP-ping, we got UDP packet back from %s port %hu (trynum = %d)\n", inet_ntoa(ip->ip_src), htons(udp->uh_sport), trynum);
}
} else if (ip->ip_p == IPPROTO_SCTP && USI->ptech.rawsctpscan) {
struct sctp_hdr *sctp = (struct sctp_hdr *) (((char *) ip) + 4 * ip->ip_hl);
struct sctp_chunkhdr *chunk = (struct sctp_chunkhdr *) ((u8 *) sctp + 12);
/* Search for this host on the incomplete list */
memset(&sin, 0, sizeof(sin));
sin.sin_addr.s_addr = ip->ip_src.s_addr;
sin.sin_family = AF_INET;
hss = USI->findHost((struct sockaddr_storage *) &sin);
if (!hss) continue; // Not from a host that interests us
probeI = hss->probes_outstanding.end();
listsz = hss->num_probes_outstanding();
goodone = false;
for(probenum = 0; probenum < listsz && !goodone; probenum++) {
probeI--;
probe = *probeI;
if (o.af() != AF_INET || probe->protocol() != IPPROTO_SCTP)
continue;
/* Ensure the connection info matches. */
if (probe->dport() != ntohs(sctp->sh_sport) ||
probe->sport() != ntohs(sctp->sh_dport) ||
hss->target->v4sourceip()->s_addr != ip->ip_dst.s_addr)
continue;
/* Sometimes we get false results when scanning localhost with
-p- because we scan localhost with src port = dst port and
see our outgoing packet and think it is a response. */
if (probe->dport() == probe->sport() &&
ip->ip_src.s_addr == ip->ip_dst.s_addr &&
probe->ipid() == ntohs(ip->ip_id))
continue; /* We saw the packet we ourselves sent */
goodone = true;
newstate = HOST_UP;
if (chunk->sch_type == SCTP_INIT_ACK) {
current_reason = ER_INITACK;
} else if (chunk->sch_type == SCTP_ABORT) {
current_reason = ER_ABORT;
} else {
current_reason = ER_UNKNOWN;
if (o.debugging)
log_write(LOG_STDOUT, "Received scan response with unexpected SCTP chunks: n/a");
}
}
} else if (!USI->ptech.rawprotoscan) {
if (o.debugging > 2)
error("Received packet with protocol %d; ignoring.", ip->ip_p);
@@ -4701,18 +5049,18 @@ static void begin_sniffer(UltraScanInfo *USI, vector<Target *> &Targets) {
pcap_filter="dst host ";
pcap_filter+=inet_ntoa(Targets[0]->v4source());
}
} else if(USI->tcp_scan || USI->udp_scan || USI->ping_scan) {
/* Handle udp and tcp with one filter. */
} else if(USI->tcp_scan || USI->udp_scan || USI->sctp_scan || USI->ping_scan) {
/* Handle udp, tcp and sctp with one filter. */
if (doIndividual){
pcap_filter="dst host ";
pcap_filter+=inet_ntoa(Targets[0]->v4source());
pcap_filter+=" and (icmp or ((tcp or udp) and (";
pcap_filter+=" and (icmp or ((tcp or udp or sctp) and (";
pcap_filter+=dst_hosts;
pcap_filter+=")))";
}else{
pcap_filter="dst host ";
pcap_filter+=inet_ntoa(Targets[0]->v4source());
pcap_filter+=" and (icmp or tcp or udp)";
pcap_filter+=" and (icmp or tcp or udp or sctp)";
}
}else assert(0);
if (o.debugging > 2) log_write(LOG_PLAIN, "Pcap filter: %s\n", pcap_filter.c_str());
@@ -5243,11 +5591,13 @@ void pos_scan(Target *target, u16 *portarray, int numports, stype scantype) {
/* Make sure we have ports left to scan */
while(1) {
if (doingOpenFiltered) {
rsi.rpc_current_port = target->ports.nextPort(rsi.rpc_current_port, TCPANDUDP,
rsi.rpc_current_port = target->ports.nextPort(rsi.rpc_current_port,
TCPANDUDPANDSCTP,
PORT_OPENFILTERED);
} else {
rsi.rpc_current_port = target->ports.nextPort(rsi.rpc_current_port,
TCPANDUDP, PORT_OPEN);
TCPANDUDPANDSCTP,
PORT_OPEN);
if (!rsi.rpc_current_port && !o.servicescan) {
doingOpenFiltered = true;
continue;

View File

@@ -107,6 +107,11 @@ struct probespec_udpdata {
u16 dport;
};
struct probespec_sctpdata {
u16 dport;
u8 chunktype;
};
struct probespec_icmpdata {
u8 type;
u8 code;
@@ -119,6 +124,7 @@ struct probespec_icmpdata {
#define PS_ICMP 4
#define PS_ARP 5
#define PS_CONNECTTCP 6
#define PS_SCTP 7
/* The size of this structure is critical, since there can be tens of
thousands of them stored together ... */
@@ -130,6 +136,7 @@ typedef struct probespec {
union {
struct probespec_tcpdata tcp; /* If type is PS_TCP or PS_CONNECTTCP. */
struct probespec_udpdata udp; /* PS_UDP */
struct probespec_sctpdata sctp; /* PS_SCTP */
struct probespec_icmpdata icmp; /* PS_ICMP */
/* Nothing needed for PS_ARP, since src mac and target IP are
avail from target structure anyway */

View File

@@ -98,6 +98,7 @@
#include "nsock.h"
#include "Target.h"
#include "utils.h"
#include "protocols.h"
#include "nmap_tty.h"
@@ -1244,6 +1245,9 @@ int AllProbes::isExcluded(unsigned short port, int proto) {
} else if (proto == IPPROTO_UDP) {
p = excludedports.udp_ports;
count = excludedports.udp_count;
} else if (proto == IPPROTO_SCTP) {
p = excludedports.sctp_ports;
count = excludedports.sctp_count;
} else {
fatal("Bad proto number (%d) specified in %s", proto, __func__);
}
@@ -1630,7 +1634,7 @@ ServiceGroup::ServiceGroup(vector<Target *> &Targets, AllProbes *AP) {
num_hosts_timedout++;
continue;
}
while((nxtport = Targets[targetno]->ports.nextPort(nxtport, TCPANDUDP, PORT_OPEN))) {
while((nxtport = Targets[targetno]->ports.nextPort(nxtport, TCPANDUDPANDSCTP, PORT_OPEN))) {
svc = new ServiceNFO(AP);
svc->target = Targets[targetno];
svc->portno = nxtport->portno;
@@ -1648,7 +1652,7 @@ ServiceGroup::ServiceGroup(vector<Target *> &Targets, AllProbes *AP) {
if (Targets[targetno]->timedOut(&now)) {
continue;
}
while((nxtport = Targets[targetno]->ports.nextPort(nxtport, TCPANDUDP, PORT_OPENFILTERED))) {
while((nxtport = Targets[targetno]->ports.nextPort(nxtport, TCPANDUDPANDSCTP, PORT_OPENFILTERED))) {
svc = new ServiceNFO(AP);
svc->target = Targets[targetno];
svc->portno = nxtport->portno;
@@ -2350,7 +2354,8 @@ static void remove_excluded_ports(AllProbes *AP, ServiceGroup *SG) {
svc = *i;
if (AP->isExcluded(svc->portno, svc->proto)) {
if (o.debugging) log_write(LOG_PLAIN, "EXCLUDING %d/%s\n", svc->portno, svc->proto==IPPROTO_TCP ? "tcp" : "udp");
if (o.debugging) log_write(LOG_PLAIN, "EXCLUDING %d/%s\n", svc->portno,
IPPROTO2STR(svc->proto));
svc->port->setServiceProbeResults(PROBESTATE_EXCLUDED, NULL,
SERVICE_TUNNEL_NONE,

View File

@@ -131,6 +131,7 @@ bool service_node_ratio_compare(const service_node& a, const service_node& b) {
extern NmapOps o;
static int numtcpports = 0;
static int numudpports = 0;
static int numsctpports = 0;
static std::map<port_spec, service_node> service_table;
static std::list<service_node> services_by_ratio;
static int services_initialized = 0;
@@ -241,6 +242,8 @@ static int nmap_services_init() {
numtcpports++;
} else if (strncasecmp(proto, "udp", 3) == 0) {
numudpports++;
} else if (strncasecmp(proto, "sctp", 4) == 0) {
numsctpports++;
} else if (strncasecmp(proto, "ddp", 3) == 0) {
/* ddp is some apple thing...we don't "do" that */
} else if (strncasecmp(proto, "divert", 6) == 0) {
@@ -300,6 +303,10 @@ int addportsfromservmask(char *mask, u8 *porttbl, int range_type) {
porttbl[ntohs(current.s_port)] |= SCAN_UDP_PORT;
t++;
}
if ((range_type & SCAN_SCTP_PORT) && strcmp(current.s_proto, "sctp") == 0) {
porttbl[ntohs(current.s_port)] |= SCAN_SCTP_PORT;
t++;
}
}
}
@@ -352,6 +359,10 @@ static bool is_port_member(const struct scan_lists *ptsdata, const struct servic
for (i=0; i<ptsdata->udp_count; i++)
if (ntohs(serv->s_port) == ptsdata->udp_ports[i])
return true;
} else if (strcmp(serv->s_proto, "sctp") == 0) {
for (i=0; i<ptsdata->sctp_count; i++)
if (ntohs(serv->s_port) == ptsdata->sctp_ports[i])
return true;
}
return false;
@@ -368,10 +379,10 @@ static bool is_port_member(const struct scan_lists *ptsdata, const struct servic
// and return the N highest ratio ports (where N==level).
//
// This function doesn't support IP protocol scan so only call this
// function if o.TCPScan() || o.UDPScan()
// function if o.TCPScan() || o.UDPScan() || o.SCTPScan()
void gettoppts(double level, char *portlist, struct scan_lists * ports) {
int ti=0, ui=0;
int ti=0, ui=0, si=0;
struct scan_lists ptsdata = { 0 };
bool ptsdata_initialized = false;
const struct service_node *current;
@@ -420,6 +431,8 @@ void gettoppts(double level, char *portlist, struct scan_lists * ports) {
ports->tcp_count++;
else if (o.UDPScan() && strcmp(current->s_proto, "udp") == 0)
ports->udp_count++;
else if (o.SCTPScan() && strcmp(current->s_proto, "sctp") == 0)
ports->sctp_count++;
} else {
break;
}
@@ -431,6 +444,9 @@ void gettoppts(double level, char *portlist, struct scan_lists * ports) {
if (ports->udp_count)
ports->udp_ports = (unsigned short *)safe_zalloc(ports->udp_count * sizeof(unsigned short));
if (ports->sctp_count)
ports->sctp_ports = (unsigned short *)safe_zalloc(ports->sctp_count * sizeof(unsigned short));
ports->prots = NULL;
for (i = services_by_ratio.begin(); i != services_by_ratio.end(); i++) {
@@ -442,6 +458,8 @@ void gettoppts(double level, char *portlist, struct scan_lists * ports) {
ports->tcp_ports[ti++] = ntohs(current->s_port);
else if (o.UDPScan() && strcmp(current->s_proto, "udp") == 0)
ports->udp_ports[ui++] = ntohs(current->s_port);
else if (o.SCTPScan() && strcmp(current->s_proto, "sctp") == 0)
ports->sctp_ports[si++] = ntohs(current->s_port);
} else {
break;
}
@@ -458,6 +476,10 @@ void gettoppts(double level, char *portlist, struct scan_lists * ports) {
ports->udp_count = MIN((int) level, numudpports);
ports->udp_ports = (unsigned short *)safe_zalloc(ports->udp_count * sizeof(unsigned short));
}
if (o.SCTPScan()) {
ports->sctp_count = MIN((int) level, numsctpports);
ports->sctp_ports = (unsigned short *)safe_zalloc(ports->sctp_count * sizeof(unsigned short));
}
ports->prots = NULL;
@@ -469,10 +491,13 @@ void gettoppts(double level, char *portlist, struct scan_lists * ports) {
ports->tcp_ports[ti++] = ntohs(current->s_port);
else if (o.UDPScan() && strcmp(current->s_proto, "udp") == 0 && ui < ports->udp_count)
ports->udp_ports[ui++] = ntohs(current->s_port);
else if (o.SCTPScan() && strcmp(current->s_proto, "sctp") == 0 && si < ports->sctp_count)
ports->sctp_ports[si++] = ntohs(current->s_port);
}
if (ti < ports->tcp_count) ports->tcp_count = ti;
if (ui < ports->udp_count) ports->udp_count = ui;
if (si < ports->sctp_count) ports->sctp_count = si;
} else
fatal("Argument to gettoppts (%g) should be a positive ratio below 1 or an integer of 1 or higher", level);
@@ -487,9 +512,12 @@ void gettoppts(double level, char *portlist, struct scan_lists * ports) {
if (ports->udp_count > 1)
qsort(ports->udp_ports, ports->udp_count, sizeof(unsigned short), &port_compare);
if (ports->sctp_count > 1)
qsort(ports->sctp_ports, ports->sctp_count, sizeof(unsigned short), &port_compare);
if (o.debugging && level < 1)
log_write(LOG_STDOUT, "PORTS: Using ports open on %g%% or more average hosts (TCP:%d, UDP:%d)\n", level*100, ports->tcp_count, ports->udp_count);
log_write(LOG_STDOUT, "PORTS: Using ports open on %g%% or more average hosts (TCP:%d, UDP:%d, SCTP:%d)\n", level*100, ports->tcp_count, ports->udp_count, ports->sctp_count);
else if (o.debugging && level >= 1)
log_write(LOG_STDOUT, "PORTS: Using top %d ports found open (TCP:%d, UDP:%d)\n", (int) level, ports->tcp_count, ports->udp_count);
log_write(LOG_STDOUT, "PORTS: Using top %d ports found open (TCP:%d, UDP:%d, SCTP:%d)\n", (int) level, ports->tcp_count, ports->udp_count, ports->sctp_count);
}

View File

@@ -111,7 +111,8 @@
*/
#define SCAN_TCP_PORT (1 << 0)
#define SCAN_UDP_PORT (1 << 1)
#define SCAN_PROTOCOLS (1 << 2)
#define SCAN_SCTP_PORT (1 << 2)
#define SCAN_PROTOCOLS (1 << 3)
int addportsfromservmask(char *mask, u8 *porttbl, int range_type);
struct servent *nmap_getservbyport(int port, const char *proto);

View File

@@ -483,7 +483,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|PINGTYPE_PROTO|PINGTYPE_ARP)) || o.RawScan()
((pingtype & (PINGTYPE_TCP|PINGTYPE_UDP|PINGTYPE_SCTP_INIT|PINGTYPE_PROTO|PINGTYPE_ARP)) || o.RawScan()
#ifdef WIN32
|| (pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS))
#endif // WIN32

View File

@@ -150,6 +150,7 @@ struct pingtech {
connecttcpscan: 1,
rawtcpscan: 1,
rawudpscan: 1,
rawsctpscan: 1,
rawprotoscan: 1;
};

View File

@@ -184,6 +184,8 @@ const char *proto2ascii(u8 proto, bool uppercase) {
return uppercase? "TCP" : "tcp"; break;
case IPPROTO_UDP:
return uppercase? "UDP" : "udp"; break;
case IPPROTO_SCTP:
return uppercase? "SCTP" : "sctp"; break;
case IPPROTO_IP:
return uppercase? "IP" : "ip"; break;
default:
@@ -427,6 +429,7 @@ static const char *ippackethdrinfo(const u8 *packet, u32 len) {
struct ip *ip = (struct ip *) packet;
struct tcp_hdr *tcp = NULL;
struct udp_hdr *udp = NULL;
struct sctp_hdr *sctp = NULL;
char ipinfo[512];
char srchost[INET6_ADDRSTRLEN], dsthost[INET6_ADDRSTRLEN];
char *p;
@@ -549,6 +552,14 @@ static const char *ippackethdrinfo(const u8 *packet, u32 len) {
Snprintf(protoinfo, sizeof(protoinfo), "UDP %s:%d > %s:%d %s",
srchost, ntohs(udp->uh_sport), dsthost, ntohs(udp->uh_dport),
ipinfo);
} else if (ip->ip_p == IPPROTO_SCTP && frag_off) {
Snprintf(protoinfo, sizeof(protoinfo), "SCTP %s:?? > %s:?? fragment %s (incomplete)", srchost, dsthost, ipinfo);
} else if (ip->ip_p == IPPROTO_SCTP) {
sctp = (struct sctp_hdr *) (packet + sizeof(struct ip));
Snprintf(protoinfo, sizeof(protoinfo), "SCTP %s:%d > %s:%d %s",
srchost, ntohs(sctp->sh_sport), dsthost, ntohs(sctp->sh_dport),
ipinfo);
} else if (ip->ip_p == IPPROTO_ICMP && frag_off) {
Snprintf(protoinfo, sizeof(protoinfo), "ICMP %s > %s fragment %s (incomplete)", srchost, dsthost, ipinfo);
} else if (ip->ip_p == IPPROTO_ICMP) {
@@ -577,6 +588,7 @@ static const char *ippackethdrinfo(const u8 *packet, u32 len) {
if (pktlen + 8 < len) {
tcp = (struct tcp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4));
udp = (struct udp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4));
sctp = (struct sctp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4));
}
ip2dst = inet_ntoa(ip2->ip_dst);
switch (ping->code) {
@@ -594,6 +606,8 @@ static const char *ippackethdrinfo(const u8 *packet, u32 len) {
Snprintf(icmptype, sizeof icmptype, "port %u unreachable", ntohs(udp->uh_dport));
else if (ip2->ip_p == IPPROTO_TCP && tcp)
Snprintf(icmptype, sizeof icmptype, "port %u unreachable", ntohs(tcp->th_dport));
else if (ip2->ip_p == IPPROTO_SCTP && sctp)
Snprintf(icmptype, sizeof icmptype, "port %u unreachable", ntohs(sctp->sh_dport));
else
strcpy(icmptype, "port unreachable");
break;
@@ -1761,6 +1775,69 @@ int send_udp_raw( int sd, struct eth_nfo *eth,
return res;
}
/* Builds an SCTP packet (including an IP header) by packing the fields
with the given information. It allocates a new buffer to store the
packet contents, and then returns that buffer. The packet is not
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_sctp_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 vtag, char *chunks, int chunkslen,
char *data, u16 datalen, u32 *outpacketlen)
{
int packetlen = sizeof(struct ip) + ipoptlen + sizeof(struct sctp_hdr) + chunkslen + datalen;
u8 *packet = (u8 *) safe_malloc(packetlen);
struct ip *ip = (struct ip *) packet;
struct sctp_hdr *sctp = (struct sctp_hdr *) ((u8*)ip + sizeof(struct ip) + ipoptlen);
static int myttl = 0;
/* check that required fields are there and not too silly */
assert(victim);
assert(source);
assert(ipoptlen%4==0);
/* Time to live */
if (ttl == -1) {
myttl = (get_random_uint() % 23) + 37;
} else {
myttl = ttl;
}
sctp->sh_sport = htons(sport);
sctp->sh_dport = htons(dport);
sctp->sh_sum = 0;
sctp->sh_vtag = htonl(vtag);
if (chunks)
memcpy((u8*)sctp + sizeof(struct sctp_hdr), chunks, chunkslen);
if (data)
memcpy((u8*)sctp + sizeof(struct sctp_hdr) + chunkslen, data, datalen);
/* RFC 2960 originally defined Adler32 checksums, which was later
* revised to CRC32C in RFC 3309 and RFC 4960 respectively.
* Nmap uses CRC32C by default, unless --adler32 is given. */
if (o.adler32)
sctp->sh_sum = htonl(nbase_adler32((unsigned char*)sctp,
sizeof(struct sctp_hdr) + chunkslen + datalen));
else
sctp->sh_sum = htonl(nbase_crc32c((unsigned char*)sctp,
sizeof(struct sctp_hdr) + chunkslen + datalen));
if (o.badsum)
--sctp->sh_sum;
fill_ip_raw(ip, packetlen, ipopt, ipoptlen,
tos, ipid, df?IP_DF:0, myttl, IPPROTO_SCTP,
source, victim);
*outpacketlen = packetlen;
return packet;
}
/* Builds an IP packet (including an IP header) by packing the fields
with the given information. It allocates a new buffer to store the
packet contents, and then returns that buffer. The packet is not

14
tcpip.h
View File

@@ -525,6 +525,20 @@ u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim,
char *data, u16 datalen,
u32 *packetlen);
/* Builds an SCTP packet (including an IP header) by packing the fields
with the given information. It allocates a new buffer to store the
packet contents, and then returns that buffer. The packet is not
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_sctp_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 vtag, char *chunks, int chunkslen,
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
store the packet contents, and then returns that buffer. The

View File

@@ -248,14 +248,16 @@ Traceroute::getTraceProbe (Target * t) {
probe = t->pingprobe;
/* If this is an IP protocol probe, fill in some fields for some common
protocols. We cheat and store them in the TCP-, UDP-, and ICMP-specific
fields. Traceroute::sendProbe checks for them there. */
protocols. We cheat and store them in the TCP-, UDP-, SCTP- and
ICMP-specific fields. Traceroute::sendProbe checks for them there. */
if (probe.type == PS_PROTO) {
if (probe.proto == IPPROTO_TCP) {
probe.pd.tcp.flags = TH_ACK;
probe.pd.tcp.dport = get_random_u16();
} else if (probe.proto == IPPROTO_UDP) {
probe.pd.udp.dport = get_random_u16();
} else if (probe.proto == IPPROTO_SCTP) {
probe.pd.sctp.dport = get_random_u16();
} else if (probe.proto == IPPROTO_ICMP) {
probe.pd.icmp.type = ICMP_ECHO;
}
@@ -274,6 +276,7 @@ Traceroute::readTraceResponses () {
struct icmp *icmp2 = NULL;
struct tcp_hdr *tcp = NULL;
struct udp_hdr *udp = NULL;
struct sctp_hdr *sctp = NULL;
struct link_header linkhdr;
unsigned int bytes;
struct timeval rcvdtime;
@@ -311,6 +314,11 @@ Traceroute::readTraceResponses () {
if (ntohs(ip2->ip_len) - (ip2->ip_hl * 4) < 2)
break;
sport = ntohs (udp->uh_sport);
} else if (ip2->ip_p == IPPROTO_SCTP) {
sctp = (struct sctp_hdr *) ((u8 *) ip2 + ip2->ip_hl * 4);
if (ntohs(ip2->ip_len) - (ip2->ip_hl * 4) < 2)
break;
sport = ntohs(sctp->sh_sport);
} else if (ip2->ip_p == IPPROTO_ICMP) {
icmp2 = (struct icmp *) ((char *) ip2 + 4 * ip2->ip_hl);
if (ntohs(ip2->ip_len) - (ip2->ip_hl * 4) < 8)
@@ -475,6 +483,43 @@ Traceroute::readTraceResponses () {
tg->ttl = tg->start_ttl + 1;
}
break;
case IPPROTO_SCTP:
sctp = (struct sctp_hdr *) ((char *) ip + 4 * ip->ip_hl);
if (TraceGroups.find(ip->ip_src.s_addr) != TraceGroups.end())
tg = TraceGroups[ip->ip_src.s_addr];
else
break;
if (tg->TraceProbes.find(ntohs(sctp->sh_dport)) != tg->TraceProbes.end())
tp = tg->TraceProbes[ntohs(sctp->sh_dport)];
else
break;
/* already got the sctp packet for this group,
* could be a left over abort or init-ack */
if (tp->ipreplysrc.s_addr)
break;
/* We might have got a late reply */
if (tp->timing.getState() == P_TIMEDOUT)
tp->timing.setState(P_OK);
else
tg->decRemaining();
tp->timing.recvTime = rcvdtime;
tp->ipreplysrc = ip->ip_src;
tg->repliedPackets++;
/* The probe was the reply from a ttl guess */
if (tp->probeType() == PROBE_TTL) {
tg->setHopDistance(get_initial_ttl_guess(ip->ip_ttl), ip->ip_ttl);
tg->start_ttl = tg->ttl = tg->hopDistance;
} else {
tg->gotReply = true;
if (tg->start_ttl < tg->ttl)
tg->ttl = tg->start_ttl + 1;
}
break;
default:
;
}
@@ -616,9 +661,9 @@ Traceroute::sendProbe (TraceProbe * tp) {
else
source = o.decoys[decoy];
/* For TCP, UDP, and ICMP, also check if the probe is an IP proto probe
whose protocol happens to be one of those protocols. The
protocol-specific fields will have been filled in by
/* For TCP, UDP, SCTP and ICMP, also check if the probe is an IP
proto probe whose protocol happens to be one of those protocols.
The protocol-specific fields will have been filled in by
Traceroute::getTraceProbe. */
if (tp->probe.type == PS_TCP
|| (tp->probe.type == PS_PROTO && tp->probe.proto == IPPROTO_TCP)) {
@@ -633,6 +678,22 @@ Traceroute::sendProbe (TraceProbe * tp) {
get_random_u8 (), false,
NULL, 0, tp->sport,
tp->probe.pd.udp.dport, o.extra_payload, o.extra_payload_length, &packetlen);
} else if (tp->probe.type == PS_SCTP
|| (tp->probe.type == PS_PROTO && tp->probe.proto == IPPROTO_SCTP)) {
struct sctp_chunkhdr_init chunk;
sctp_pack_chunkhdr_init(&chunk, SCTP_INIT, 0,
sizeof(struct sctp_chunkhdr_init),
get_random_u32()/*itag*/,
32768, 10, 2048,
get_random_u32()/*itsn*/);
packet = build_sctp_raw(&source, &tp->ipdst, tp->ttl,
get_random_u16(), get_random_u8(),
false, NULL, 0,
tp->sport, tp->probe.pd.sctp.dport,
0UL, (char*)&chunk,
sizeof(struct sctp_chunkhdr_init),
o.extra_payload, o.extra_payload_length,
&packetlen);
} else if (tp->probe.type == PS_ICMP
|| (tp->probe.type == PS_PROTO && tp->probe.proto == IPPROTO_ICMP)) {
packet = build_icmp_raw (&source, &tp->ipdst, tp->ttl, 0, 0, false,
@@ -951,6 +1012,8 @@ Traceroute::outputTarget (Target * t) {
log_write(LOG_PLAIN, "\nTRACEROUTE (using port %d/%s)\n", tg->probe.pd.tcp.dport, proto2ascii(tg->probe.proto));
} else if (tg->probe.type == PS_UDP) {
log_write(LOG_PLAIN, "\nTRACEROUTE (using port %d/%s)\n", tg->probe.pd.udp.dport, proto2ascii(tg->probe.proto));
} else if (tg->probe.type == PS_SCTP) {
log_write(LOG_PLAIN, "\nTRACEROUTE (using port %d/%s)\n", tg->probe.pd.sctp.dport, proto2ascii(tg->probe.proto));
} else if (tg->probe.type == PS_ICMP || tg->probe.type == PS_PROTO) {
struct protoent *proto = nmap_getprotbynum(htons(tg->probe.proto));
log_write(LOG_PLAIN, "\nTRACEROUTE (using proto %d/%s)\n", tg->probe.proto, proto?proto->p_name:"unknown");
@@ -982,6 +1045,8 @@ Traceroute::outputXMLTrace(TraceGroup * tg) {
log_write(LOG_XML, "port=\"%d\" ", tg->probe.pd.tcp.dport);
} else if (tg->probe.type == PS_UDP) {
log_write(LOG_XML, "port=\"%d\" ", tg->probe.pd.udp.dport);
} else if (tg->probe.type == PS_SCTP) {
log_write(LOG_XML, "port=\"%d\" ", tg->probe.pd.sctp.dport);
} else if (tg->probe.type == PS_ICMP || tg->probe.type == PS_PROTO) {
struct protoent *proto = nmap_getprotbynum(htons(tg->probe.proto));
if (proto == NULL)
@@ -1108,7 +1173,7 @@ TraceGroup::retransmissions (vector < TraceProbe * >&retrans) {
if (droppedPackets > 10 && (droppedPackets /
((double) droppedPackets + repliedPackets) > threshold)) {
if (!scanDelay)
scanDelay = (probe.type == PS_TCP) ? 5 : 50;
scanDelay = (probe.type == PS_TCP || probe.type == PS_SCTP) ? 5 : 50;
else
scanDelay = MIN (scanDelay * 2, MAX (scanDelay, 800));
droppedPackets = 0;