Author: tuexen
Date: Wed Aug 22 21:23:32 2018
New Revision: 338213
URL: https://svnweb.freebsd.org/changeset/base/338213

Log:
  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

Added:
  
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh
   (contents, props changed)
  
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out
  
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh
   (contents, props changed)
  
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out
  
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh
   (contents, props changed)
  
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out
  
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh
   (contents, props changed)
  
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out
  head/cddl/lib/libdtrace/sctp.d   (contents, props changed)
Modified:
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
  head/cddl/lib/libdtrace/Makefile
  head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile
  head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh
  head/share/man/man4/dtrace_sctp.4
  head/sys/netinet/in_kdtrace.c
  head/sys/netinet/in_kdtrace.h
  head/sys/netinet/sctp_dtrace_define.h
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_output.c
  head/sys/netinet/sctputil.c

Modified: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
==============================================================================
--- 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl   
    Wed Aug 22 21:22:40 2018        (r338212)
+++ 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl   
    Wed Aug 22 21:23:32 2018        (r338213)
@@ -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;

Added: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh
   Wed Aug 22 21:23:32 2018        (r338213)
@@ -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

Added: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out
       Wed Aug 22 21:23:32 2018        (r338213)
@@ -0,0 +1,7 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+sctp:::send - yes
+sctp:::receive - yes
+

Added: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh
  Wed Aug 22 21:23:32 2018        (r338213)
@@ -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

Added: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out
      Wed Aug 22 21:23:32 2018        (r338213)
@@ -0,0 +1,7 @@
+Minimum SCTP events seen
+
+ip:::send - yes
+ip:::receive - yes
+sctp:::send - yes
+sctp:::receive - yes
+

Added: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh
  Wed Aug 22 21:23:32 2018        (r338213)
@@ -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

Added: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out
      Wed Aug 22 21:23:32 2018        (r338213)
@@ -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

Added: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh
 Wed Aug 22 21:23:32 2018        (r338213)
@@ -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

Added: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out
     Wed Aug 22 21:23:32 2018        (r338213)
@@ -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
+

Modified: head/cddl/lib/libdtrace/Makefile
==============================================================================
--- head/cddl/lib/libdtrace/Makefile    Wed Aug 22 21:22:40 2018        
(r338212)
+++ head/cddl/lib/libdtrace/Makefile    Wed Aug 22 21:23:32 2018        
(r338213)
@@ -51,6 +51,7 @@ DSRCS=                errno.d                 \
                io.d                    \
                ip.d                    \
                psinfo.d                \
+               sctp.d                  \
                siftr.d                 \
                signal.d                \
                tcp.d                   \

Added: head/cddl/lib/libdtrace/sctp.d
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/cddl/lib/libdtrace/sctp.d      Wed Aug 22 21:23:32 2018        
(r338213)
@@ -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 <tue...@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;
+};

Modified: head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile
==============================================================================
--- head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile  Wed Aug 22 21:22:40 
2018        (r338212)
+++ head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile  Wed Aug 22 21:23:32 
2018        (r338213)
@@ -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  \
 

Modified: head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh
==============================================================================
--- head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh    Wed Aug 22 21:22:40 
2018        (r338212)
+++ head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh    Wed Aug 22 21:23:32 
2018        (r338213)
@@ -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.

Modified: head/share/man/man4/dtrace_sctp.4
==============================================================================
--- head/share/man/man4/dtrace_sctp.4   Wed Aug 22 21:22:40 2018        
(r338212)
+++ head/share/man/man4/dtrace_sctp.4   Wed Aug 22 21:23:32 2018        
(r338213)
@@ -23,7 +23,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 1, 2018
+.Dd August 22, 2018
 .Dt DTRACE_SCTP 4
 .Os
 .Sh NAME
@@ -44,6 +44,12 @@ protocol
 .Fn sctp:rwnd:assoc:val uint32_t uint32_t int int
 .Fn sctp:flightsize:net:val uint32_t uint32_t uintptr_t int int
 .Fn sctp:flightsize:assoc:val uint32_t uint32_t int int
+.Fn sctp:::receive "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "sctpsinfo_t *" \
+    "sctpinfo_t *"
+.Fn sctp:::send "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "sctpsinfo_t *" \
+    "sctpinfo_t *"
+.Fn sctp:::state-change "void *" "csinfo_t *" "void *" "sctpsinfo_t *" \
+    "void *" "sctplsinfo_t *"
 .Sh DESCRIPTION
 The DTrace
 .Nm sctp
@@ -105,14 +111,105 @@ probe fires when a remotely-initiated active SCTP open
 At this point the new connection is in the ESTABLISHED state, and the probe
 arguments expose the headers associated with the final ACK of the four-way
 handshake.
+.Pp
+The
+.Fn sctp:::send
+and
+.Fn sctp:::receive
+probes fire when the host sends or receives an SCTP packet, respectively.
+As with the
+.Xr dtrace_udp 4
+provider,
+.Nm sctp
+probes fire only for packets sent by or to the local host; forwarded packets 
are
+handled in the IP layer and are only visible to the
+.Xr dtrace_ip 4
+provider.
+.Pp
+The
+.Fn sctp:::state-change
+probe fires upon local SCTP association state transitions.
+Its first, third and fifth arguments are currently always
+.Dv NULL .
+Its last argument describes the from-state in the transition, and the to-state
+can be obtained from
+.Dv args[3]->sctps_state .
 .\" .Sh ARGUMENTS
-.\" .Sh FILES
-.\" .Sh EXAMPLES
-.\" .Sh COMPATIBILITY
-.\" This provider has not been tested for compatiblity with the
-.\" .Nm sctp
-.\" provider in Solaris
-.\" .Pq if one exists .
+.Sh FILES
+.Bl -tag -width "/usr/lib/dtrace/sctp.d" -compact
+.It Pa /usr/lib/dtrace/sctp.d
+DTrace type and translator definitions for the
+.Nm sctp
+provider.
+.El
+.Sh EXAMPLES
+A script that logs SCTP packets in real time:
+.Bd -literal -offset indent
+#pragma D option quiet
+#pragma D option switchrate=10hz
+
+dtrace:::BEGIN
+{
+        printf(" %3s %15s:%-5s      %15s:%-5s\n", "CPU",
+            "LADDR", "LPORT", "RADDR", "RPORT");
+}
+
+sctp:::send
+{
+        printf(" %3d %16s:%-5d -> %16s:%-5d\n", cpu,
+            args[2]->ip_saddr, args[4]->sctp_sport,
+            args[2]->ip_daddr, args[4]->sctp_dport);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to