Index: cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl =================================================================== --- cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl +++ 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 @@ 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 @@ 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; Index: cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh =================================================================== --- cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh +++ 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: " + 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 <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 Index: cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out =================================================================== --- cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localsctp.ksh.out +++ 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 + Index: cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh =================================================================== --- cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh +++ 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: " + 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 <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 Index: cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out =================================================================== --- cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotesctp.ksh.out +++ 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 + Index: cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh =================================================================== --- cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh +++ 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: " + 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 <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 Index: cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out =================================================================== --- cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localsctpstate.ksh.out +++ 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 Index: cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh =================================================================== --- cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh +++ 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: " + 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 <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 Index: cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out =================================================================== --- cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotesctpstate.ksh.out +++ 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 + Index: cddl/lib/libdtrace/Makefile =================================================================== --- cddl/lib/libdtrace/Makefile +++ cddl/lib/libdtrace/Makefile @@ -51,6 +51,7 @@ io.d \ ip.d \ psinfo.d \ + sctp.d \ siftr.d \ signal.d \ tcp.d \ Index: cddl/lib/libdtrace/sctp.d =================================================================== --- cddl/lib/libdtrace/sctp.d +++ 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 + */ + +#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" : + ""; + +/* + * 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 ? "" : + p->asoc.primary_destination == NULL ? "" : + p->asoc.primary_destination->ro._s_addr == NULL ? "" : + 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) : + ""; + sctps_raddr = p == NULL ? "" : + p->asoc.primary_destination == NULL ? "" : + 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) : + ""; + 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; +}; Index: cddl/usr.sbin/dtrace/tests/common/ip/Makefile =================================================================== --- cddl/usr.sbin/dtrace/tests/common/ip/Makefile +++ cddl/usr.sbin/dtrace/tests/common/ip/Makefile @@ -9,6 +9,8 @@ ${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 @@ 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 @@ 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 \ Index: cddl/usr.sbin/dtrace/tests/tools/exclude.sh =================================================================== --- cddl/usr.sbin/dtrace/tests/tools/exclude.sh +++ cddl/usr.sbin/dtrace/tests/tools/exclude.sh @@ -117,11 +117,13 @@ 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. Index: share/man/man4/dtrace_sctp.4 =================================================================== --- share/man/man4/dtrace_sctp.4 +++ share/man/man4/dtrace_sctp.4 @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 1, 2018 +.Dd August 23, 2018 .Dt DTRACE_SCTP 4 .Os .Sh NAME @@ -44,6 +44,12 @@ .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,99 @@ 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 +The following script 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); +} + +sctp:::receive +{ + printf(" %3d %16s:%-5d <- %16s:%-5d\n", cpu, + args[2]->ip_daddr, args[4]->sctp_dport, + args[2]->ip_saddr, args[4]->sctp_sport); +} +.Ed +The following script logs SCTP assocation state changes as they occur: +.Bd -literal -offset indent +#pragma D option quiet +#pragma D option switchrate=10 + +int last[int]; + +dtrace:::BEGIN +{ + printf(" %3s %12s %-25s %-25s\n", + "CPU", "DELTA(us)", "OLD", "NEW"); +} + +sctp:::state-change +/ last[args[1]->cs_cid] / +{ + this->elapsed = (timestamp - last[args[1]->cs_cid]) / 1000; + printf(" %3d %12d %-25s -> %-25s\n", cpu, this->elapsed, + sctp_state_string[args[5]->sctps_state], + sctp_state_string[args[3]->sctps_state]); + last[args[1]->cs_cid] = timestamp; +} + +sctp:::state-change +/ last[args[1]->cs_cid] == 0 / +{ + printf(" %3d %12s %-25s -> %-25s\n", cpu, "-", + sctp_state_string[args[5]->sctps_state], + sctp_state_string[args[3]->sctps_state]); + last[args[1]->cs_cid] = timestamp; +} +.Ed +.Sh COMPATIBILITY +This provider is compatible with the +.Nm sctp +provider in Solaris. .Sh SEE ALSO .Xr dtrace 1 , .Xr dtrace_ip 4 , Index: sys/netinet/in_kdtrace.h =================================================================== --- sys/netinet/in_kdtrace.h +++ sys/netinet/in_kdtrace.h @@ -48,14 +48,31 @@ SDT_PROBE5(tcp, , , probe, arg0, arg1, arg2, arg3, arg4) #define TCP_PROBE6(probe, arg0, arg1, arg2, arg3, arg4, arg5) \ SDT_PROBE6(tcp, , , probe, arg0, arg1, arg2, arg3, arg4, arg5) +#define SCTP_PROBE1(probe, arg0) \ + SDT_PROBE1(sctp, , , probe, arg0) +#define SCTP_PROBE2(probe, arg0, arg1) \ + SDT_PROBE2(sctp, , , probe, arg0, arg1) +#define SCTP_PROBE3(probe, arg0, arg1, arg2) \ + SDT_PROBE3(sctp, , , probe, arg0, arg1, arg2) +#define SCTP_PROBE4(probe, arg0, arg1, arg2, arg3) \ + SDT_PROBE4(sctp, , , probe, arg0, arg1, arg2, arg3) +#define SCTP_PROBE5(probe, arg0, arg1, arg2, arg3, arg4) \ + SDT_PROBE5(sctp, , , probe, arg0, arg1, arg2, arg3, arg4) +#define SCTP_PROBE6(probe, arg0, arg1, arg2, arg3, arg4, arg5) \ + SDT_PROBE6(sctp, , , probe, arg0, arg1, arg2, arg3, arg4, arg5) SDT_PROVIDER_DECLARE(ip); +SDT_PROVIDER_DECLARE(sctp); SDT_PROVIDER_DECLARE(tcp); SDT_PROVIDER_DECLARE(udp); SDT_PROVIDER_DECLARE(udplite); SDT_PROBE_DECLARE(ip, , , receive); SDT_PROBE_DECLARE(ip, , , send); + +SDT_PROBE_DECLARE(sctp, , , receive); +SDT_PROBE_DECLARE(sctp, , , send); +SDT_PROBE_DECLARE(sctp, , , state__change); SDT_PROBE_DECLARE(tcp, , , accept__established); SDT_PROBE_DECLARE(tcp, , , accept__refused); Index: sys/netinet/in_kdtrace.c =================================================================== --- sys/netinet/in_kdtrace.c +++ sys/netinet/in_kdtrace.c @@ -36,6 +36,7 @@ #include SDT_PROVIDER_DEFINE(ip); +SDT_PROVIDER_DEFINE(sctp); SDT_PROVIDER_DEFINE(tcp); SDT_PROVIDER_DEFINE(udp); SDT_PROVIDER_DEFINE(udplite); @@ -55,6 +56,28 @@ "struct ifnet *", "ifinfo_t *", "struct ip *", "ipv4info_t *", "struct ip6_hdr *", "ipv6info_t *"); + +SDT_PROBE_DEFINE5_XLATE(sctp, , , receive, + "void *", "pktinfo_t *", + "struct sctp_tcb *", "csinfo_t *", + "struct mbuf *", "ipinfo_t *", + "struct sctp_tcb *", "sctpsinfo_t *" , + "struct sctphdr *", "sctpinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(sctp, , , send, + "void *", "pktinfo_t *", + "struct sctp_tcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct sctp_tcb *", "sctpsinfo_t *" , + "struct sctphdr *", "sctpinfo_t *"); + +SDT_PROBE_DEFINE6_XLATE(sctp, , , state__change, + "void *", "void *", + "struct sctp_tcb *", "csinfo_t *", + "void *", "void *", + "struct sctp_tcb *", "sctpsinfo_t *", + "void *", "void *", + "int", "sctplsinfo_t *"); SDT_PROBE_DEFINE5_XLATE(tcp, , , accept__established, "void *", "pktinfo_t *", Index: sys/netinet/sctp_dtrace_define.h =================================================================== --- sys/netinet/sctp_dtrace_define.h +++ sys/netinet/sctp_dtrace_define.h @@ -40,7 +40,7 @@ #include #include -SDT_PROVIDER_DEFINE(sctp); +SDT_PROVIDER_DECLARE(sctp); /********************************************************/ /* Cwnd probe - tracks changes in the congestion window on a netp */ Index: sys/netinet/sctp_input.c =================================================================== --- sys/netinet/sctp_input.c +++ sys/netinet/sctp_input.c @@ -52,6 +52,7 @@ #if defined(INET) || defined(INET6) #include #endif +#include #include @@ -5569,6 +5570,7 @@ net->flowtype = mflowtype; net->flowid = mflowid; } + SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh); if ((inp != NULL) && (stcb != NULL)) { sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); @@ -5609,6 +5611,7 @@ net->flowid = mflowid; } if (inp == NULL) { + SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh); SCTP_STAT_INCR(sctps_noport); if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) { goto out; @@ -5657,6 +5660,7 @@ */ SCTP_TCB_UNLOCK(stcb); stcb = NULL; + SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh); snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); @@ -5713,11 +5717,13 @@ if ((stcb != NULL) && sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) { /* "silently" ignore */ + SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh); SCTP_STAT_INCR(sctps_recvauthmissing); goto out; } if (stcb == NULL) { /* out of the blue DATA chunk */ + SCTP_PROBE5(receive, NULL, NULL, m, NULL, sh); snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); @@ -5728,11 +5734,13 @@ } if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) { /* v_tag mismatch! */ + SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh); SCTP_STAT_INCR(sctps_badvtag); goto out; } } + SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh); if (stcb == NULL) { /* * no valid TCB for this packet, or we found it's a bad Index: sys/netinet/sctp_output.c =================================================================== --- sys/netinet/sctp_output.c +++ sys/netinet/sctp_output.c @@ -57,6 +57,7 @@ #endif #include #include +#include @@ -4251,6 +4252,7 @@ SCTP_SOCKET_UNLOCK(so, 0); } #endif + SCTP_PROBE5(send, NULL, stcb, ip, stcb, sctphdr); SCTP_IP_OUTPUT(ret, o_pak, ro, stcb, vrf_id); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) { @@ -4584,6 +4586,7 @@ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) sctp_packet_log(o_pak); #endif + SCTP_PROBE5(send, NULL, stcb, ip6h, stcb, sctphdr); SCTP_IP6_OUTPUT(ret, o_pak, (struct route_in6 *)ro, &ifp, stcb, vrf_id); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) if ((SCTP_BASE_SYSCTL(sctp_output_unlocked)) && (so_locked)) { @@ -11252,6 +11255,7 @@ sctp_packet_log(o_pak); } #endif + SCTP_PROBE5(send, NULL, NULL, ip, NULL, shout); SCTP_IP_OUTPUT(ret, o_pak, NULL, NULL, vrf_id); break; #endif @@ -11274,6 +11278,7 @@ sctp_packet_log(o_pak); } #endif + SCTP_PROBE5(send, NULL, NULL, ip6, NULL, shout); SCTP_IP6_OUTPUT(ret, o_pak, NULL, NULL, NULL, vrf_id); break; #endif Index: sys/netinet/sctputil.c =================================================================== --- sys/netinet/sctputil.c +++ sys/netinet/sctputil.c @@ -56,6 +56,7 @@ #endif #include #include +#include #include #ifdef INET6 #include @@ -7385,6 +7386,10 @@ void sctp_set_state(struct sctp_tcb *stcb, int new_state) { +#if defined(KDTRACE_HOOKS) + int old_state = stcb->asoc.state; +#endif + KASSERT((new_state & ~SCTP_STATE_MASK) == 0, ("sctp_set_state: Can't set substate (new_state = %x)", new_state)); @@ -7394,13 +7399,32 @@ (new_state == SCTP_STATE_SHUTDOWN_ACK_SENT)) { SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING); } +#if defined(KDTRACE_HOOKS) + if (((old_state & SCTP_STATE_MASK) != new_state) && + !(((old_state & SCTP_STATE_MASK) == SCTP_STATE_EMPTY) && + (new_state == SCTP_STATE_INUSE))) { + SCTP_PROBE6(state__change, NULL, stcb, NULL, stcb, NULL, old_state); + } +#endif } void sctp_add_substate(struct sctp_tcb *stcb, int substate) { +#if defined(KDTRACE_HOOKS) + int old_state = stcb->asoc.state; +#endif + KASSERT((substate & SCTP_STATE_MASK) == 0, ("sctp_add_substate: Can't set state (substate = %x)", substate)); stcb->asoc.state |= substate; +#if defined(KDTRACE_HOOKS) + if (((substate & SCTP_STATE_ABOUT_TO_BE_FREED) && + ((old_state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) || + ((substate & SCTP_STATE_SHUTDOWN_PENDING) && + ((old_state & SCTP_STATE_SHUTDOWN_PENDING) == 0))) { + SCTP_PROBE6(state__change, NULL, stcb, NULL, stcb, NULL, old_state); + } +#endif }