aboutsummaryrefslogtreecommitdiff
path: root/cddl
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2018-08-22 21:23:32 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2018-08-22 21:23:32 +0000
commit1e88cc8b598adf0160666c7fd540699c22c5c447 (patch)
tree4f1be5b2c158506950247c3b7b186d8c8ac433d9 /cddl
parent376a4e32558ce3566ee7cfcaf21d15a437275373 (diff)
downloadsrc-1e88cc8b598adf0160666c7fd540699c22c5c447.tar.gz
src-1e88cc8b598adf0160666c7fd540699c22c5c447.zip
Add support for send, receive and state-change DTrace providers for
SCTP. They are based on what is specified in the Solaris DTrace manual for Solaris 11.4. Reviewed by: 0mp, dteske, markj Relnotes: yes Differential Revision: https://reviews.freebsd.org/D16839
Notes
Notes: svn path=/head/; revision=338213
Diffstat (limited to 'cddl')
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl17
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh137
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out7
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh130
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out7
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh159
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out12
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh149
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out12
-rw-r--r--cddl/lib/libdtrace/Makefile1
-rw-r--r--cddl/lib/libdtrace/sctp.d171
-rw-r--r--cddl/usr.sbin/dtrace/tests/common/ip/Makefile8
-rwxr-xr-xcddl/usr.sbin/dtrace/tests/tools/exclude.sh2
13 files changed, 805 insertions, 7 deletions
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
index 5f58eb8e0ca8..c07e46bbd976 100755
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
@@ -27,11 +27,12 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#
-# get.ipv4remote.pl [tcpport]
+# get.ipv4remote.pl [port] [proto]
#
# Find an IPv4 reachable remote host using both ifconfig(1M) and ping(1M).
-# If a tcpport is specified, return a host that is also listening on this
-# TCP port. Print the local address and the remote address, or an
+# If a port is specified, return a host that is also listening on this
+# port. If the port is specified, the protocol can also be specified and
+# defaults to tcp. Print the local address and the remote address, or an
# error message if no suitable remote host was found. Exit status is 0 if
# a host was found.
#
@@ -41,7 +42,8 @@ use IO::Socket;
my $MAXHOSTS = 32; # max hosts to port scan
my $TIMEOUT = 3; # connection timeout
-my $tcpport = @ARGV == 1 ? $ARGV[0] : 0;
+my $port = @ARGV >= 1 ? $ARGV[0] : 0;
+my $proto = @ARGV == 2 ? $ARGV[1] : "tcp";
#
# Determine local IP address
@@ -79,14 +81,15 @@ while (<PING>) {
if (/bytes from (.*): / and not defined $Broadcast{$1}) {
my $addr = $1;
- if ($tcpport != 0) {
+ if ($port != 0) {
#
# Test TCP
#
my $socket = IO::Socket::INET->new(
- Proto => "tcp",
+ Type => SOCK_STREAM,
+ Proto => $proto,
PeerAddr => $addr,
- PeerPort => $tcpport,
+ PeerPort => $port,
Timeout => $TIMEOUT,
);
next unless $socket;
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh
new file mode 100755
index 000000000000..594ef71dc597
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh
@@ -0,0 +1,137 @@
+#!/usr/bin/env ksh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# Test {ip,sctp}:::{send,receive} of IPv4 SCTP to local host.
+#
+# This may fail due to:
+#
+# 1. A change to the ip stack breaking expected probe behavior,
+# which is the reason we are testing.
+# 2. The lo0 interface missing or not up.
+# 3. An unlikely race causes the unlocked global send/receive
+# variables to be corrupted.
+#
+# This test performs a SCTP association and checks that at least the
+# following packet counts were traced:
+#
+# 7 x ip:::send (4 during the setup, 3 during the teardown)
+# 7 x sctp:::send (4 during the setup, 3 during the teardown)
+# 7 x ip:::receive (4 during the setup, 3 during the teardown)
+# 7 x sctp:::receive (4 during the setup, 3 during the teardown)
+
+# The actual count tested is 7 each way, since we are tracing both
+# source and destination events.
+#
+
+if (( $# != 1 )); then
+ print -u2 "expected one argument: <dtrace-path>"
+ exit 2
+fi
+
+dtrace=$1
+local=127.0.0.1
+DIR=/var/tmp/dtest.$$
+
+sctpport=1024
+bound=5000
+while [ $sctpport -lt $bound ]; do
+ ncat --sctp -z $local $sctpport > /dev/null || break
+ sctpport=$(($sctpport + 1))
+done
+if [ $sctpport -eq $bound ]; then
+ echo "couldn't find an available SCTP port"
+ exit 1
+fi
+
+mkdir $DIR
+cd $DIR
+
+# ncat will exit when the association is closed.
+ncat --sctp --listen $local $sctpport &
+
+cat > test.pl <<-EOPERL
+ use IO::Socket;
+ my \$s = IO::Socket::INET->new(
+ Type => SOCK_STREAM,
+ Proto => "sctp",
+ LocalAddr => "$local",
+ PeerAddr => "$local",
+ PeerPort => $sctpport,
+ Timeout => 3);
+ die "Could not connect to host $local port $sctpport \$@" unless \$s;
+ close \$s;
+ sleep(2);
+EOPERL
+
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
+BEGIN
+{
+ ipsend = sctpsend = ipreceive = sctpreceive = 0;
+}
+
+ip:::send
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+ args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+ ipsend++;
+}
+
+sctp:::send
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local"/
+{
+ sctpsend++;
+}
+
+ip:::receive
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+ args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+ ipreceive++;
+}
+
+sctp:::receive
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local"/
+{
+ sctpreceive++;
+}
+
+END
+{
+ printf("Minimum SCTP events seen\n\n");
+ printf("ip:::send (%d) - %s\n", ipsend, ipsend >= 7 ? "yes" : "no");
+ printf("ip:::receive (%d) - %s\n", ipreceive, ipreceive >= 7 ? "yes" : "no");
+ printf("sctp:::send (%d) - %s\n", sctpsend, sctpsend >= 7 ? "yes" : "no");
+ printf("sctp:::receive (%d) - %s\n", sctpreceive, sctpreceive >= 7 ? "yes" : "no");
+}
+EODTRACE
+
+status=$?
+
+cd /
+/bin/rm -rf $DIR
+
+exit $status
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out
new file mode 100644
index 000000000000..8c708770971b
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out
@@ -0,0 +1,7 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+sctp:::send - yes
+sctp:::receive - yes
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh
new file mode 100755
index 000000000000..60dabf7a8b94
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh
@@ -0,0 +1,130 @@
+#!/usr/bin/env ksh93
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# Test {sctp,ip}:::{send,receive} of IPv4 SCTP to a remote host.
+#
+# This may fail due to:
+#
+# 1. A change to the ip stack breaking expected probe behavior,
+# which is the reason we are testing.
+# 2. No physical network interface is plumbed and up.
+# 3. No other hosts on this subnet are reachable and listening on ssh.
+# 4. An unlikely race causes the unlocked global send/receive
+# variables to be corrupted.
+#
+# This test performs an SCTP association and checks that at least the
+# following packet counts were traced:
+#
+# 4 x ip:::send (2 during setup, 2 during teardown)
+# 4 x sctp:::send (2 during connection setup, 2 during connection teardown)
+# 3 x ip:::receive (2 during setup, 1 during teardown)
+# 3 x sctp:::receive (2 during setup, 1 during teardown)
+
+if (( $# != 1 )); then
+ print -u2 "expected one argument: <dtrace-path>"
+ exit 2
+fi
+
+dtrace=$1
+getaddr=./get.ipv4remote.pl
+sctpport=80
+DIR=/var/tmp/dtest.$$
+
+if [[ ! -x $getaddr ]]; then
+ print -u2 "could not find or execute sub program: $getaddr"
+ exit 3
+fi
+$getaddr $sctpport sctp | read source dest
+if (( $? != 0 )); then
+ exit 4
+fi
+
+mkdir $DIR
+cd $DIR
+
+cat > test.pl <<-EOPERL
+ use IO::Socket;
+ my \$s = IO::Socket::INET->new(
+ Type => SOCK_STREAM,
+ Proto => "sctp",
+ LocalAddr => "$source",
+ PeerAddr => "$dest",
+ PeerPort => $sctpport,
+ Timeout => 3);
+ die "Could not connect to host $dest port $sctpport \$@" unless \$s;
+ close \$s;
+ sleep(2);
+EOPERL
+
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
+BEGIN
+{
+ ipsend = sctpsend = ipreceive = sctpreceive = 0;
+}
+
+ip:::send
+/args[2]->ip_saddr == "$source" && args[2]->ip_daddr == "$dest" &&
+ args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+ ipsend++;
+}
+
+sctp:::send
+/args[2]->ip_saddr == "$source" && args[2]->ip_daddr == "$dest"/
+{
+ sctpsend++;
+}
+
+ip:::receive
+/args[2]->ip_saddr == "$dest" && args[2]->ip_daddr == "$source" &&
+ args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+ ipreceive++;
+}
+
+sctp:::receive
+/args[2]->ip_saddr == "$dest" && args[2]->ip_daddr == "$source"/
+{
+ sctpreceive++;
+}
+
+END
+{
+ printf("Minimum SCTP events seen\n\n");
+ printf("ip:::send - %s\n", ipsend >= 4 ? "yes" : "no");
+ printf("ip:::receive - %s\n", ipreceive >= 3 ? "yes" : "no");
+ printf("sctp:::send - %s\n", sctpsend >= 4 ? "yes" : "no");
+ printf("sctp:::receive - %s\n", sctpreceive >= 3 ? "yes" : "no");
+}
+EODTRACE
+
+status=$?
+
+cd /
+/bin/rm -rf $DIR
+
+exit $status
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out
new file mode 100644
index 000000000000..8c708770971b
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out
@@ -0,0 +1,7 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+sctp:::send - yes
+sctp:::receive - yes
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh
new file mode 100755
index 000000000000..7fb21644b459
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh
@@ -0,0 +1,159 @@
+#!/usr/bin/env ksh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# Test sctp:::state-change and sctp:::{send,receive} by connecting to
+# the local discard service.
+# A number of state transition events along with SCTP send and
+# receive events for the message should result.
+#
+# This may fail due to:
+#
+# 1. A change to the ip stack breaking expected probe behavior,
+# which is the reason we are testing.
+# 2. The lo0 interface missing or not up.
+# 3. An unlikely race causes the unlocked global send/receive
+# variables to be corrupted.
+#
+# This test performs a SCTP connection and checks that at least the
+# following packet counts were traced:
+#
+# 7 x ip:::send (4 during the setup, 3 during the teardown)
+# 7 x sctp:::send (4 during the setup, 3 during the teardown)
+# 7 x ip:::receive (4 during the setup, 3 during the teardown)
+# 7 x sctp:::receive (4 during the setup, 3 during the teardown)
+#
+# The actual count tested is 7 each way, since we are tracing both
+# source and destination events.
+#
+
+if (( $# != 1 )); then
+ print -u2 "expected one argument: <dtrace-path>"
+ exit 2
+fi
+
+dtrace=$1
+local=127.0.0.1
+DIR=/var/tmp/dtest.$$
+
+sctpport=1024
+bound=5000
+while [ $sctpport -lt $bound ]; do
+ ncat --sctp -z $local $sctpport > /dev/null || break
+ sctpport=$(($sctpport + 1))
+done
+if [ $sctpport -eq $bound ]; then
+ echo "couldn't find an available SCTP port"
+ exit 1
+fi
+
+mkdir $DIR
+cd $DIR
+
+# ncat will exit when the association is closed.
+ncat --sctp --listen $local $sctpport &
+
+cat > test.pl <<-EOPERL
+ use IO::Socket;
+ my \$s = IO::Socket::INET->new(
+ Type => SOCK_STREAM,
+ Proto => "sctp",
+ LocalAddr => "$local",
+ PeerAddr => "$local",
+ PeerPort => $sctpport,
+ Timeout => 3);
+ die "Could not connect to host $local port $sctpport \$@" unless \$s;
+ close \$s;
+ sleep(2);
+EOPERL
+
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
+BEGIN
+{
+ ipsend = sctpsend = ipreceive = sctpreceive = 0;
+}
+
+ip:::send
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+ args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+ ipsend++;
+}
+
+sctp:::send
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+ (args[4]->sctp_sport == $sctpport || args[4]->sctp_dport == $sctpport)/
+{
+ sctpsend++;
+}
+
+ip:::receive
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+ args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+ ipreceive++;
+}
+
+sctp:::receive
+/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" &&
+ (args[4]->sctp_sport == $sctpport || args[4]->sctp_dport == $sctpport)/
+{
+ sctpreceive++;
+}
+
+sctp:::state-change
+{
+ state_event[args[3]->sctps_state]++;
+}
+
+END
+{
+ printf("Minimum SCTP events seen\n\n");
+ printf("ip:::send - %s\n", ipsend >= 7 ? "yes" : "no");
+ printf("ip:::receive - %s\n", ipreceive >= 7 ? "yes" : "no");
+ printf("sctp:::send - %s\n", sctpsend >= 7 ? "yes" : "no");
+ printf("sctp:::receive - %s\n", sctpreceive >= 7 ? "yes" : "no");
+ printf("sctp:::state-change to cookie-wait - %s\n",
+ state_event[SCTP_STATE_COOKIE_WAIT] >=1 ? "yes" : "no");
+ printf("sctp:::state-change to cookie-echoed - %s\n",
+ state_event[SCTP_STATE_COOKIE_ECHOED] >=1 ? "yes" : "no");
+ printf("sctp:::state-change to established - %s\n",
+ state_event[SCTP_STATE_ESTABLISHED] >= 2 ? "yes" : "no");
+ printf("sctp:::state-change to shutdown-sent - %s\n",
+ state_event[SCTP_STATE_SHUTDOWN_SENT] >= 1 ? "yes" : "no");
+ printf("sctp:::state-change to shutdown-received - %s\n",
+ state_event[SCTP_STATE_SHUTDOWN_RECEIVED] >= 1 ? "yes" : "no");
+ printf("sctp:::state-change to shutdown-ack-sent - %s\n",
+ state_event[SCTP_STATE_SHUTDOWN_ACK_SENT] >= 1 ? "yes" : "no");
+}
+EODTRACE
+
+status=$?
+
+cd /
+/bin/rm -rf $DIR
+
+exit $status
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out
new file mode 100644
index 000000000000..8fe345a1785b
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out
@@ -0,0 +1,12 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+sctp:::send - yes
+sctp:::receive - yes
+sctp:::state-change to cookie-wait - yes
+sctp:::state-change to cookie-echoed - yes
+sctp:::state-change to established - yes
+sctp:::state-change to shutdown-sent - yes
+sctp:::state-change to shutdown-received - yes
+sctp:::state-change to shutdown-ack-sent - yes
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh
new file mode 100755
index 000000000000..3209c04e042c
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh
@@ -0,0 +1,149 @@
+#!/usr/bin/env ksh93
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# Test sctp:::state-change and sctp:::{send,receive} by connecting to
+# the remote http service.
+# A number of state transition events along with sctp send and receive
+# events for the message should result.
+#
+# This may fail due to:
+#
+# 1. A change to the ip stack breaking expected probe behavior,
+# which is the reason we are testing.
+# 2. The lo0 interface missing or not up.
+# 3. The remote ssh service is not online.
+# 4. An unlikely race causes the unlocked global send/receive
+# variables to be corrupted.
+#
+# This test performs a SCTP association to the http service (port 80) and
+# checks that at least the following packet counts were traced:
+#
+# 4 x ip:::send (2 during setup, 2 during teardown)
+# 4 x sctp:::send (2 during setup, 2 during teardown)
+# 3 x ip:::receive (2 during setup, 1 during teardown)
+# 3 x sctp:::receive (2 during setup, 1 during teardown)
+#
+
+if (( $# != 1 )); then
+ print -u2 "expected one argument: <dtrace-path>"
+ exit 2
+fi
+
+dtrace=$1
+getaddr=./get.ipv4remote.pl
+sctpport=80
+DIR=/var/tmp/dtest.$$
+
+if [[ ! -x $getaddr ]]; then
+ print -u2 "could not find or execute sub program: $getaddr"
+ exit 3
+fi
+$getaddr $sctpport sctp | read source dest
+if (( $? != 0 )); then
+ exit 4
+fi
+
+mkdir $DIR
+cd $DIR
+
+cat > test.pl <<-EOPERL
+ use IO::Socket;
+ my \$s = IO::Socket::INET->new(
+ Type => SOCK_STREAM,
+ Proto => "sctp",
+ LocalAddr => "$source",
+ PeerAddr => "$dest",
+ PeerPort => $sctpport,
+ Timeout => 3);
+ die "Could not connect to host $dest port $sctpport \$@" unless \$s;
+ close \$s;
+ sleep(2);
+EOPERL
+
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
+BEGIN
+{
+ ipsend = sctpsend = ipreceive = sctpreceive = 0;
+}
+
+ip:::send
+/args[2]->ip_saddr == "$source" && args[2]->ip_daddr == "$dest" &&
+ args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+ ipsend++;
+}
+
+sctp:::send
+/args[2]->ip_saddr == "$source" && args[2]->ip_daddr == "$dest" &&
+ args[4]->sctp_dport == $sctpport/
+{
+ sctpsend++;
+}
+
+ip:::receive
+/args[2]->ip_saddr == "$dest" && args[2]->ip_daddr == "$source" &&
+ args[4]->ipv4_protocol == IPPROTO_SCTP/
+{
+ ipreceive++;
+}
+
+sctp:::receive
+/args[2]->ip_saddr == "$dest" && args[2]->ip_daddr == "$source" &&
+ args[4]->sctp_sport == $sctpport/
+{
+ sctpreceive++;
+}
+
+sctp:::state-change
+{
+ state_event[args[3]->sctps_state]++;
+}
+
+END
+{
+ printf("Minimum SCTP events seen\n\n");
+ printf("ip:::send - %s\n", ipsend >= 4 ? "yes" : "no");
+ printf("ip:::receive - %s\n", ipreceive >= 3 ? "yes" : "no");
+ printf("sctp:::send - %s\n", sctpsend >= 4 ? "yes" : "no");
+ printf("sctp:::receive - %s\n", sctpreceive >= 3 ? "yes" : "no");
+ printf("sctp:::state-change to cookie-wait - %s\n",
+ state_event[SCTP_STATE_COOKIE_WAIT] >=1 ? "yes" : "no");
+ printf("sctp:::state-change to cookie-echoed - %s\n",
+ state_event[SCTP_STATE_COOKIE_ECHOED] >= 1 ? "yes" : "no");
+ printf("sctp:::state-change to established - %s\n",
+ state_event[SCTP_STATE_ESTABLISHED] >= 1 ? "yes" : "no");
+ printf("sctp:::state-change to shutdown-sent - %s\n",
+ state_event[SCTP_STATE_SHUTDOWN-SENT] >= 1 ? "yes" : "no");
+}
+EODTRACE
+
+status=$?
+
+cd /
+/bin/rm -rf $DIR
+
+exit $status
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out
new file mode 100644
index 000000000000..a39b14fcfcb3
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out
@@ -0,0 +1,12 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+SCTP:::send - yes
+sctp:::receive - yes
+sctp:::state-change to cookie-wait - yes
+sctp:::state-change to cookie-echoed - yes
+sctp:::state-change to established - yes
+sctp:::state-change to shutdown-sent - yes
+sctp:::state-change to closed - yes
+
diff --git a/cddl/lib/libdtrace/Makefile b/cddl/lib/libdtrace/Makefile
index 13cf557ad53e..bc58855ffc5d 100644
--- a/cddl/lib/libdtrace/Makefile
+++ b/cddl/lib/libdtrace/Makefile
@@ -51,6 +51,7 @@ DSRCS= errno.d \
io.d \
ip.d \
psinfo.d \
+ sctp.d \
siftr.d \
signal.d \
tcp.d \
diff --git a/cddl/lib/libdtrace/sctp.d b/cddl/lib/libdtrace/sctp.d
new file mode 100644
index 000000000000..5dc776bdb971
--- /dev/null
+++ b/cddl/lib/libdtrace/sctp.d
@@ -0,0 +1,171 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * $FreeBSD$
+ */
+/*
+ * Copyright (c) 2018 Michael Tuexen <tuexen@FreeBSD.org>
+ */
+
+#pragma D depends_on library ip.d
+#pragma D depends_on library socket.d
+#pragma D depends_on module kernel
+#pragma D depends_on provider sctp
+
+#pragma D binding "1.13" SCTP_STATE_MASK
+inline int32_t SCTP_STATE_MASK = 0x0000007f;
+#pragma D binding "1.13" SCTP_STATE_SHUTDOWN_PENDING
+inline int32_t SCTP_STATE_SHUTDOWN_PENDING = 0x00000080;
+#pragma D binding "1.13" SCTP_STATE_CLOSED_SOCKET
+inline int32_t SCTP_STATE_CLOSED_SOCKET = 0x00000100;
+#pragma D binding "1.13" SCTP_STATE_ABOUT_TO_BE_FREED
+inline int32_t SCTP_STATE_ABOUT_TO_BE_FREED = 0x00000200;
+#pragma D binding "1.13" SCTP_STATE_ABOUT_TO_BE_FREED
+inline int32_t SCTP_STATE_PARTIAL_MSG_LEFT = 0x00000400;
+#pragma D binding "1.13" SCTP_STATE_PARTIAL_MSG_LEFT
+inline int32_t SCTP_STATE_WAS_ABORTED = 0x00000800;
+#pragma D binding "1.13" SCTP_STATE_IN_ACCEPT_QUEUE
+inline int32_t SCTP_STATE_IN_ACCEPT_QUEUE = 0x00001000;
+#pragma D binding "1.13" SCTP_STATE_BOUND
+inline int32_t SCTP_STATE_BOUND = 0x00001000;
+#pragma D binding "1.13" SCTP_STATE_EMPTY
+inline int32_t SCTP_STATE_EMPTY = 0x00000000;
+#pragma D binding "1.13" SCTP_STATE_CLOSED
+inline int32_t SCTP_STATE_CLOSED = 0x00000000;
+#pragma D binding "1.13" SCTP_STATE_INUSE
+inline int32_t SCTP_STATE_INUSE = 0x00000001;
+#pragma D binding "1.13" SCTP_STATE_COOKIE_WAIT
+inline int32_t SCTP_STATE_COOKIE_WAIT = 0x00000002;
+#pragma D binding "1.13" SCTP_STATE_COOKIE_ECHOED
+inline int32_t SCTP_STATE_COOKIE_ECHOED = 0x00000004;
+#pragma D binding "1.13" SCTP_STATE_ESTABLISHED
+inline int32_t SCTP_STATE_ESTABLISHED = 0x00000008;
+#pragma D binding "1.13" SCTP_STATE_OPEN
+inline int32_t SCTP_STATE_OPEN = 0x00000008;
+#pragma D binding "1.13" SCTP_STATE_SHUTDOWN_SENT
+inline int32_t SCTP_STATE_SHUTDOWN_SENT = 0x00000010;
+#pragma D binding "1.13" SCTP_STATE_SHUTDOWN_RECEIVED
+inline int32_t SCTP_STATE_SHUTDOWN_RECEIVED = 0x00000020;
+#pragma D binding "1.13" SCTP_STATE_SHUTDOWN_ACK_SENT
+inline int32_t SCTP_STATE_SHUTDOWN_ACK_SENT = 0x00000040;
+
+/* SCTP association state strings. */
+#pragma D binding "1.13" sctp_state_string
+inline string sctp_state_string[int32_t state] =
+ state & SCTP_STATE_ABOUT_TO_BE_FREED ? "state-closed" :
+ state & SCTP_STATE_SHUTDOWN_PENDING ? "state-shutdown-pending" :
+ (state & SCTP_STATE_MASK) == SCTP_STATE_EMPTY ? "state-closed" :
+ (state & SCTP_STATE_MASK) == SCTP_STATE_INUSE ? "state-closed" :
+ (state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT ? "state-cookie-wait" :
+ (state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED ? "state-cookie-echoed" :
+ (state & SCTP_STATE_MASK) == SCTP_STATE_OPEN ? "state-established" :
+ (state & SCTP_STATE_MASK) == SCTP_STATE_SHUTDOWN_SENT ? "state-shutdown-sent" :
+ (state & SCTP_STATE_MASK) == SCTP_STATE_SHUTDOWN_RECEIVED ? "state-shutdown-received" :
+ (state & SCTP_STATE_MASK) == SCTP_STATE_SHUTDOWN_ACK_SENT ? "state-shutdown-ack-sent" :
+ "<unknown>";
+
+/*
+ * sctpsinfo contains stable SCTP details.
+ */
+typedef struct sctpsinfo {
+ uintptr_t sctps_addr; /* pointer to struct sctp_tcb */
+ int sctps_num_raddrs; /* number of remote addresses */
+ uintptr_t sctps_raddrs; /* pointer to struct sctp_nets */
+ int sctps_num_laddrs; /* number of local addresses */
+ uintptr_t sctps_laddrs; /* pointer to struct sctp_laddr */
+ uint16_t sctps_lport; /* local port */
+ uint16_t sctps_rport; /* remote port */
+ string sctps_laddr; /* local address, as a string */
+ string sctps_raddr; /* remote address, as a string */
+ int32_t sctps_state;
+} sctpsinfo_t;
+
+/*
+ * sctplsinfo provides the old SCTP state for state changes.
+ */
+typedef struct sctplsinfo {
+ int32_t sctps_state; /* previous SCTP state */
+} sctplsinfo_t;
+
+/*
+ * sctpinfo is the SCTP header fields.
+ */
+typedef struct sctpinfo {
+ uint16_t sctp_sport; /* source port */
+ uint16_t sctp_dport; /* destination port */
+ uint32_t sctp_verify; /* verification tag */
+ uint32_t sctp_checksum; /* CRC32C of the SCTP packet */
+ struct sctphdr *sctp_hdr; /* raw SCTP header */
+} sctpinfo_t;
+
+#pragma D binding "1.13" translator
+translator csinfo_t < struct sctp_tcb *p > {
+ cs_addr = NULL;
+ cs_cid = (uint64_t)p;
+ cs_pid = 0;
+ cs_zoneid = 0;
+};
+
+#pragma D binding "1.13" translator
+translator sctpsinfo_t < struct sctp_tcb *p > {
+ sctps_addr = (uintptr_t)p;
+ sctps_num_raddrs = p == NULL ? -1 : p->asoc.numnets;
+ sctps_raddrs = p == NULL ? NULL : (uintptr_t)(p->asoc.nets.tqh_first);
+ sctps_num_laddrs = p == NULL ? -1 :
+ p->sctp_ep == NULL ? -1 :
+ p->sctp_ep->laddr_count;
+ sctps_laddrs = p == NULL ? NULL :
+ p->sctp_ep == NULL ? NULL :
+ (uintptr_t)(p->sctp_ep->sctp_addr_list.lh_first);
+ sctps_lport = p == NULL ? 0 :
+ p->sctp_ep == NULL ? 0 :
+ ntohs(p->sctp_ep->ip_inp.inp.inp_inc.inc_ie.ie_lport);
+ sctps_rport = p == NULL ? 0 : ntohs(p->rport);
+ sctps_laddr = p == NULL ? "<unknown>" :
+ p->asoc.primary_destination == NULL ? "<unknown>" :
+ p->asoc.primary_destination->ro._s_addr == NULL ? "<unknown>" :
+ p->asoc.primary_destination->ro._s_addr->address.sa.sa_family == AF_INET ?
+ inet_ntoa(&p->asoc.primary_destination->ro._s_addr->address.sin.sin_addr.s_addr) :
+ p->asoc.primary_destination->ro._s_addr->address.sa.sa_family == AF_INET6 ?
+ inet_ntoa6(&p->asoc.primary_destination->ro._s_addr->address.sin6.sin6_addr) :
+ "<unknown>";
+ sctps_raddr = p == NULL ? "<unknown>" :
+ p->asoc.primary_destination == NULL ? "<unknown>" :
+ p->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET ?
+ inet_ntoa(&p->asoc.primary_destination->ro._l_addr.sin.sin_addr.s_addr) :
+ p->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET6 ?
+ inet_ntoa6(&p->asoc.primary_destination->ro._l_addr.sin6.sin6_addr) :
+ "<unknown>";
+ sctps_state = p == NULL ? SCTP_STATE_CLOSED : p->asoc.state;
+};
+
+#pragma D binding "1.13" translator
+translator sctpinfo_t < struct sctphdr *p > {
+ sctp_sport = p == NULL ? 0 : ntohs(p->src_port);
+ sctp_dport = p == NULL ? 0 : ntohs(p->dest_port);
+ sctp_verify = p == NULL ? 0 : ntohl(p->v_tag);
+ sctp_checksum = p == NULL ? 0 : ntohl(p->checksum);
+ sctp_hdr = p;
+};
+
+#pragma D binding "1.13" translator
+translator sctplsinfo_t < int state > {
+ sctps_state = state;
+};
diff --git a/cddl/usr.sbin/dtrace/tests/common/ip/Makefile b/cddl/usr.sbin/dtrace/tests/common/ip/Makefile
index c47aac901cb4..25a214b7f37b 100644
--- a/cddl/usr.sbin/dtrace/tests/common/ip/Makefile
+++ b/cddl/usr.sbin/dtrace/tests/common/ip/Makefile
@@ -9,6 +9,8 @@ PACKAGE= tests
${PACKAGE}FILES= \
tst.ipv4localicmp.ksh \
tst.ipv4localicmp.ksh.out \
+ tst.ipv4localsctp.ksh \
+ tst.ipv4localsctp.ksh.out \
tst.ipv4localtcp.ksh \
tst.ipv4localtcp.ksh.out \
tst.ipv4localudp.ksh \
@@ -17,6 +19,8 @@ ${PACKAGE}FILES= \
tst.ipv4localudplite.ksh.out \
tst.ipv4remoteicmp.ksh \
tst.ipv4remoteicmp.ksh.out \
+ tst.ipv4remotesctp.ksh \
+ tst.ipv4remotesctp.ksh.out \
tst.ipv4remotetcp.ksh \
tst.ipv4remotetcp.ksh.out \
tst.ipv4remoteudp.ksh \
@@ -27,8 +31,12 @@ ${PACKAGE}FILES= \
tst.ipv6localicmp.ksh.out \
tst.ipv6remoteicmp.ksh \
tst.ipv6remoteicmp.ksh.out \
+ tst.localsctpstate.ksh \
+ tst.localsctpstate.ksh.out \
tst.localtcpstate.ksh \
tst.localtcpstate.ksh.out \
+ tst.remotesctpstate.ksh \
+ tst.remotesctpstate.ksh.out \
tst.remotetcpstate.ksh \
tst.remotetcpstate.ksh.out \
diff --git a/cddl/usr.sbin/dtrace/tests/tools/exclude.sh b/cddl/usr.sbin/dtrace/tests/tools/exclude.sh
index 1a4d8bd7cdb9..db5796039a0d 100755
--- a/cddl/usr.sbin/dtrace/tests/tools/exclude.sh
+++ b/cddl/usr.sbin/dtrace/tests/tools/exclude.sh
@@ -117,11 +117,13 @@ exclude SKIP common/builtinvar/tst.ipl.d
exclude SKIP common/builtinvar/tst.ipl1.d
# These tests rely on being able to find a host via broadcast pings.
+exclude EXFAIL common/ip/tst.ipv4remotesctp.ksh
exclude EXFAIL common/ip/tst.ipv4remotetcp.ksh
exclude EXFAIL common/ip/tst.ipv4remoteudp.ksh
exclude EXFAIL common/ip/tst.ipv4remoteudplite.ksh
exclude EXFAIL common/ip/tst.ipv6remoteicmp.ksh
exclude EXFAIL common/ip/tst.ipv4remoteicmp.ksh
+exclude EXFAIL common/ip/tst.remotesctpstate.ksh
exclude EXFAIL common/ip/tst.remotetcpstate.ksh
# Tries to enable pid$target:libc::entry, though there's no "libc" module.