From 6a2be621a033b50cf99905e6318d145aaf41d04a Mon Sep 17 00:00:00 2001
From: Michael Tuexen <tuexen@fh-muenster.de>
Date: Mon, 20 Jul 2015 09:38:14 +0200
Subject: [PATCH] Add structures for the SCTP_STATUS socket option.

Please note that packetdrill currently does not support
getsockopt() for non int values.
---
 gtests/net/packetdrill/contrib/packetdrill.el |   2 +-
 .../net/packetdrill/contrib/packetdrill.plist |   8 +
 .../net/packetdrill/contrib/packetdrill.vim   |   2 +-
 gtests/net/packetdrill/lexer.l                | 238 +++++++++---------
 gtests/net/packetdrill/parser.y               |  44 ++++
 gtests/net/packetdrill/run_system_call.c      |   4 +
 gtests/net/packetdrill/script.c               |  12 +
 gtests/net/packetdrill/script.h               |   6 +
 gtests/net/packetdrill/symbols_freebsd.c      |  11 +
 gtests/net/packetdrill/symbols_linux.c        |  13 +
 gtests/net/packetdrill/types.h                |  15 ++
 11 files changed, 238 insertions(+), 117 deletions(-)

diff --git a/gtests/net/packetdrill/contrib/packetdrill.el b/gtests/net/packetdrill/contrib/packetdrill.el
index 239971f2..7aa999ee 100644
--- a/gtests/net/packetdrill/contrib/packetdrill.el
+++ b/gtests/net/packetdrill/contrib/packetdrill.el
@@ -1,4 +1,4 @@
-(setq packetdrill-keywords '("sa_family" "sin_port" "sin_addr" "msg_name" "msg_iov" "msg_flags" "fd" "events" "revents" "htons" "icmp" "sctp" "udp" "udplite" "inet_addr" "ack" "eol" "ecr" "mss" "mtu" "nop" "sack" "sackOK" "TS" "FO" "LS" "gcn" "minRTO" "val" "win" "wscale" "ect01" "ect0" "ect1" "noecn" "ce" "pro" "onoff" "linger" "srto_initial" "srto_max" "srto_min" "sinit_num_ostreams" "sinit_max_instreams" "sinit_max_attempts" "sinit_max_init_timeo" "assoc_value" "sack_delay" "sack_freq"))
+(setq packetdrill-keywords '("sa_family" "sin_port" "sin_addr" "msg_name" "msg_iov" "msg_flags" "fd" "events" "revents" "htons" "icmp" "sctp" "udp" "udplite" "inet_addr" "ack" "eol" "ecr" "mss" "mtu" "nop" "sack" "sackOK" "TS" "FO" "LS" "gcn" "minRTO" "val" "win" "wscale" "ect01" "ect0" "ect1" "noecn" "ce" "pro" "onoff" "linger" "srto_initial" "srto_max" "srto_min" "sinit_num_ostreams" "sinit_max_instreams" "sinit_max_attempts" "sinit_max_init_timeo" "assoc_value" "sack_delay" "sack_freq" "sstat_state" "sstat_rwnd" "sstat_unackdata" "sstat_penddata" "sstat_instrms" "sstat_outstrms" "sstat_fragmentation_point" "sstat_primary"))
 
 (setq packetdrill-constants '("AF_INET" "AF_INET6" "PF_INET" "PF_INET6" "SOCK_STREAM" "SOCK_DGRAM" "IPPROTO_IP" "IPPROTO_IPV6" "IPPROTO_ICMP" "IPPROTO_SCTP" "IPPROTO_TCP" "IPPROTO_UDP" "IPPROTO_UDPLITE" "SOL_SOCKET" "SOL_IP" "SOL_IPV6" "SOL_SCTP" "SOL_TCP" "SOL_UDP" "SO_ACCEPTCONN" "SO_ATTACH_FILTER" "SO_BINDTODEVICE" "SO_BROADCAST" "SO_BSDCOMPAT" "SO_DEBUG" "SO_DETACH_FILTER" "SO_DONTROUTE" "SO_ERROR" "SO_KEEPALIVE" "SO_LINGER" "SO_NO_CHECK" "SO_OOBINLINE" "SO_PASSCRED" "SO_PEERCRED" "SO_PEERNAME" "SO_PEERSEC" "SO_PRIORITY" "SO_RCVBUF" "SO_RCVLOWAT" "SO_RCVTIMEO" "SO_REUSEADDR" "SO_REUSEPORT" "SO_SECURITY_AUTHENTICATION" "SO_SECURITY_ENCRYPTION_NETWORK" "SO_SECURITY_ENCRYPTION_TRANSPORT" "SO_SNDBUF" "SO_SNDLOWAT" "SO_SNDTIMEO" "SO_TIMESTAMP" "SO_TYPE" "IP_TOS" "IP_MTU_DISCOVER" "IP_PMTUDISC_WANT" "IP_PMTUDISC_DONT" "IP_PMTUDISC_DO" "IP_PMTUDISC_PROBE" "IP_MTU" "IPV6_MTU" "SCTP_RTOINFO" "SCTP_INITMSG" "SCTP_NODELAY" "SCTP_MAXSEG" "SCTP_DELAYED_SACK" "SCTP_MAX_BURST" "TCP_NODELAY" "TCP_MAXSEG" "TCP_CORK" "TCP_KEEPIDLE" "TCP_KEEPINTVL" "TCP_KEEPCNT" "TCP_SYNCNT" "TCP_LINGER2" "TCP_DEFER_ACCEPT" "TCP_WINDOW_CLAMP" "TCP_INFO" "TCP_QUICKACK" "TCP_CONGESTION" "TCP_MD5SIG" "TCP_COOKIE_TRANSACTIONS" "TCP_THIN_LINEAR_TIMEOUTS" "TCP_THIN_DUPACK" "TCP_USER_TIMEOUT" "TCP_MIN_RTO" "TCP_INFO_EXT" "TCP_CWND" "TCP_XMIT_COMPL_SEQ" "TCP_CWND_CLAMP" "TCP_SAVE_SYN" "TCP_SAVED_SYN" "TCP_FASTOPEN" "TCP_MULTIPLE_CONNECTIONS" "UDPLITE_RECV_CSCOV" "UDPLITE_SEND_CSCOV" "O_RDONLY" "O_WRONLY" "O_RDWR" "O_ACCMODE" "O_CREAT" "O_EXCL" "O_NOCTTY" "O_TRUNC" "O_APPEND" "O_NONBLOCK" "F_DUPFD" "F_GETFD" "F_SETFD" "F_GETFL" "F_SETFL" "F_GETLK" "F_SETLK" "F_SETLKW" "F_GETOWN" "F_SETOWN" "F_SETSIG" "F_GETSIG" "F_GETOWN" "F_SETOWN" "F_SETLK" "F_SETLKW" "F_GETLK" "F_SETLK64" "F_SETLKW64" "F_GETLK64" "F_SETLEASE" "F_GETLEASE" "F_NOTIFY" "F_DUPFD_CLOEXEC" "FD_CLOEXEC" "LOCK_SH" "LOCK_EX" "LOCK_NB" "LOCK_UN" "F_RDLCK" "F_WRLCK" "F_UNLCK" "F_EXLCK" "F_SHLCK" "SEEK_SET" "SEEK_CUR" "SEEK_END" "MSG_OOB" "MSG_DONTROUTE" "MSG_PEEK" "MSG_CTRUNC" "MSG_PROXY" "MSG_EOR" "MSG_WAITALL" "MSG_TRUNC" "MSG_CTRUNC" "MSG_ERRQUEUE" "MSG_DONTWAIT" "MSG_CONFIRM" "MSG_FIN" "MSG_SYN" "MSG_RST" "MSG_NOSIGNAL" "MSG_MORE" "MSG_CMSG_CLOEXEC" "MSG_FASTOPEN" "SIOCINQ" "FIONREAD" "POLLIN" "POLLPRI" "POLLOUT" "POLLRDNORM" "POLLRDBAND" "POLLWRNORM" "POLLWRBAND" "POLLMSG" "POLLREMOVE" "POLLRDHUP" "POLLERR" "POLLHUP" "POLLNVAL" "EPERM" "ENOENT" "ESRCH" "EINTR" "EIO" "ENXIO" "E2BIG" "ENOEXEC" "EBADF" "ECHILD" "EAGAIN" "ENOMEM" "EACCES" "EFAULT" "ENOTBLK" "EBUSY" "EEXIST" "EXDEV" "ENODEV" "ENOTDIR" "EISDIR" "EINVAL" "ENFILE" "EMFILE" "ENOTTY" "ETXTBSY" "EFBIG" "ENOSPC" "ESPIPE" "EROFS" "EMLINK" "EPIPE" "EDOM" "ERANGE" "EDEADLK" "ENAMETOOLONG" "ENOLCK" "ENOSYS" "ENOTEMPTY" "ELOOP" "EWOULDBLOCK" "ENOMSG" "EIDRM" "ECHRNG" "EL2NSYNC" "EL3HLT" "EL3RST" "ELNRNG" "EUNATCH" "ENOCSI" "EL2HLT" "EBADE" "EBADR" "EXFULL" "ENOANO" "EBADRQC" "EBADSLT" "EDEADLOCK" "EBFONT" "ENOSTR" "ENODATA" "ETIME" "ENOSR" "ENONET" "ENOPKG" "EREMOTE" "ENOLINK" "EADV" "ESRMNT" "ECOMM" "EPROTO" "EMULTIHOP" "EDOTDOT" "EBADMSG" "EOVERFLOW" "ENOTUNIQ" "EBADFD" "EREMCHG" "ELIBACC" "ELIBBAD" "ELIBSCN" "ELIBMAX" "ELIBEXEC" "EILSEQ" "ERESTART" "ESTRPIPE" "EUSERS" "ENOTSOCK" "EDESTADDRREQ" "EMSGSIZE" "EPROTOTYPE" "ENOPROTOOPT" "EPROTONOSUPPORT" "ESOCKTNOSUPPORT" "EOPNOTSUPP" "EPFNOSUPPORT" "EAFNOSUPPORT" "EADDRINUSE" "EADDRNOTAVAIL" "ENETDOWN" "ENETUNREACH" "ENETRESET" "ECONNABORTED" "ECONNRESET" "ENOBUFS" "EISCONN" "ENOTCONN" "ESHUTDOWN" "ETOOMANYREFS" "ETIMEDOUT" "ECONNREFUSED" "EHOSTDOWN" "EHOSTUNREACH" "EALREADY" "EINPROGRESS" "ESTALE" "EUCLEAN" "ENOTNAM" "ENAVAIL" "EISNAM" "EREMOTEIO" "EDQUOT" "ENOMEDIUM" "EMEDIUMTYPE" "ECANCELED" "ENOKEY" "EKEYEXPIRED" "EKEYREVOKED" "EKEYREJECTED" "EOWNERDEAD" "ENOTRECOVERABLE" "ERFKILL" "POLLIN" "POLLPRI" "POLLOUT" "POLLRDNORM" "POLLRDBAND" "POLLWRNORM" "POLLWRBAND" "POLLMSG" "POLLREMOVE" "POLLRDHUP" "POLLERR" "POLLHUP" "POLLNVAL"))
 
diff --git a/gtests/net/packetdrill/contrib/packetdrill.plist b/gtests/net/packetdrill/contrib/packetdrill.plist
index e9a374ad..978645f5 100644
--- a/gtests/net/packetdrill/contrib/packetdrill.plist
+++ b/gtests/net/packetdrill/contrib/packetdrill.plist
@@ -72,6 +72,14 @@
 		<string>assoc_value</string>
 		<string>sack_delay</string>
 		<string>sack_freq</string>
+		<string>sstat_state</string>
+		<string>sstat_rwnd</string>
+		<string>sstat_unackdata</string>
+		<string>sstat_penddata</string>
+		<string>sstat_instrms</string>
+		<string>sstat_outstrms</string>
+		<string>sstat_fragmentation_point</string>
+		<string>sstat_primary</string>
 	</array>
 	<key>BBLMPredefinedNameList</key>
 	<array>
diff --git a/gtests/net/packetdrill/contrib/packetdrill.vim b/gtests/net/packetdrill/contrib/packetdrill.vim
index 4b7bac4e..7401ffd4 100644
--- a/gtests/net/packetdrill/contrib/packetdrill.vim
+++ b/gtests/net/packetdrill/contrib/packetdrill.vim
@@ -11,7 +11,7 @@ endif
 let s:cpo_save = &cpo
 set cpo&vim
 
-syn keyword     pKeyword        sa_family sin_port sin_addr msg_name msg_iov msg_flags fd events revents htons icmp sctp udp udplite inet_addr ack eol ecr mss mtu nop sack sackOK TS FO LS gcn minRTO val win wscale ect01 ect0 ect1 noecn ce pro onoff linger srto_initial srto_max srto_min sinit_num_ostreams sinit_max_instreams sinit_max_attempts sinit_max_init_timeo assoc_value sack_delay sack_freq
+syn keyword     pKeyword        sa_family sin_port sin_addr msg_name msg_iov msg_flags fd events revents htons icmp sctp udp udplite inet_addr ack eol ecr mss mtu nop sack sackOK TS FO LS gcn minRTO val win wscale ect01 ect0 ect1 noecn ce pro onoff linger srto_initial srto_max srto_min sinit_num_ostreams sinit_max_instreams sinit_max_attempts sinit_max_init_timeo assoc_value sack_delay sack_freq sstat_state sstat_rwnd sstat_unackdata sstat_penddata sstat_instrms sstat_outstrms sstat_fragmentation_point sstat_primary
 syn keyword     pConstant       AF_INET AF_INET6 PF_INET PF_INET6 SOCK_STREAM SOCK_DGRAM IPPROTO_IP IPPROTO_IPV6 IPPROTO_ICMP IPPROTO_SCTP IPPROTO_TCP IPPROTO_UDP IPPROTO_UDPLITE SOL_SOCKET SOL_IP SOL_IPV6 SOL_SCTP SOL_TCP SOL_UDP SOL_UDPLITE SO_ACCEPTCONN SO_ATTACH_FILTER SO_BINDTODEVICE SO_BROADCAST SO_BSDCOMPAT SO_DEBUG SO_DETACH_FILTER SO_DONTROUTE SO_ERROR SO_KEEPALIVE SO_LINGER SO_NO_CHECK SO_OOBINLINE SO_PASSCRED SO_PEERCRED SO_PEERNAME SO_PEERSEC SO_PRIORITY SO_RCVBUF SO_RCVLOWAT SO_RCVTIMEO SO_REUSEADDR SO_REUSEPORT SO_SECURITY_AUTHENTICATION SO_SECURITY_ENCRYPTION_NETWORK SO_SECURITY_ENCRYPTION_TRANSPORT SO_SNDBUF SO_SNDLOWAT SO_SNDTIMEO SO_TIMESTAMP SO_TYPE IP_TOS IP_MTU_DISCOVER IP_PMTUDISC_WANT IP_PMTUDISC_DONT IP_PMTUDISC_DO IP_PMTUDISC_PROBE IP_MTU IPV6_MTU SCTP_RTOINFO SCTP_INITMSG SCTP_NODELAY SCTP_MAXSEG SCTP_DELAYED_SACK SCTP_MAX_BURST TCP_NODELAY TCP_MAXSEG TCP_CORK TCP_KEEPIDLE TCP_KEEPINTVL TCP_KEEPCNT TCP_SYNCNT TCP_LINGER2 TCP_DEFER_ACCEPT TCP_WINDOW_CLAMP TCP_INFO TCP_QUICKACK TCP_CONGESTION TCP_MD5SIG TCP_COOKIE_TRANSACTIONS TCP_THIN_LINEAR_TIMEOUTS TCP_THIN_DUPACK TCP_USER_TIMEOUT TCP_MIN_RTO TCP_INFO_EXT TCP_CWND TCP_XMIT_COMPL_SEQ TCP_CWND_CLAMP TCP_SAVE_SYN TCP_SAVED_SYN TCP_FASTOPEN TCP_MULTIPLE_CONNECTIONS UDPLITE_RECV_CSCOV UDPLITE_SEND_CSCOV
 syn keyword     pConstant       O_RDONLY O_WRONLY O_RDWR O_ACCMODE O_CREAT O_EXCL O_NOCTTY O_TRUNC O_APPEND O_NONBLOCK F_DUPFD F_GETFD F_SETFD F_GETFL F_SETFL F_GETLK F_SETLK F_SETLKW F_GETOWN F_SETOWN F_SETSIG F_GETSIG F_GETOWN F_SETOWN F_SETLK F_SETLKW F_GETLK F_SETLK64 F_SETLKW64 F_GETLK64 F_SETLEASE F_GETLEASE F_NOTIFY F_DUPFD_CLOEXEC FD_CLOEXEC LOCK_SH LOCK_EX LOCK_NB LOCK_UN F_RDLCK F_WRLCK F_UNLCK F_EXLCK F_SHLCK SEEK_SET SEEK_CUR SEEK_END MSG_OOB MSG_DONTROUTE MSG_PEEK MSG_CTRUNC MSG_PROXY MSG_EOR MSG_WAITALL MSG_TRUNC MSG_CTRUNC MSG_ERRQUEUE MSG_DONTWAIT MSG_CONFIRM MSG_FIN MSG_SYN MSG_RST MSG_NOSIGNAL MSG_MORE MSG_CMSG_CLOEXEC MSG_FASTOPEN SIOCINQ FIONREAD POLLIN POLLPRI POLLOUT POLLRDNORM POLLRDBAND POLLWRNORM POLLWRBAND POLLMSG POLLREMOVE POLLRDHUP POLLERR POLLHUP POLLNVAL EPERM ENOENT ESRCH EINTR EIO ENXIO E2BIG ENOEXEC EBADF ECHILD EAGAIN ENOMEM EACCES EFAULT ENOTBLK EBUSY EEXIST EXDEV ENODEV ENOTDIR EISDIR EINVAL ENFILE EMFILE ENOTTY ETXTBSY EFBIG ENOSPC ESPIPE EROFS EMLINK EPIPE EDOM ERANGE EDEADLK ENAMETOOLONG ENOLCK ENOSYS ENOTEMPTY ELOOP EWOULDBLOCK ENOMSG EIDRM ECHRNG EL2NSYNC EL3HLT EL3RST ELNRNG EUNATCH ENOCSI EL2HLT EBADE EBADR EXFULL ENOANO EBADRQC EBADSLT EDEADLOCK EBFONT ENOSTR ENODATA ETIME ENOSR ENONET ENOPKG EREMOTE ENOLINK EADV ESRMNT ECOMM EPROTO EMULTIHOP EDOTDOT EBADMSG EOVERFLOW ENOTUNIQ EBADFD EREMCHG ELIBACC ELIBBAD ELIBSCN ELIBMAX ELIBEXEC EILSEQ ERESTART ESTRPIPE EUSERS ENOTSOCK EDESTADDRREQ EMSGSIZE EPROTOTYPE ENOPROTOOPT EPROTONOSUPPORT ESOCKTNOSUPPORT EOPNOTSUPP EPFNOSUPPORT EAFNOSUPPORT EADDRINUSE EADDRNOTAVAIL ENETDOWN ENETUNREACH ENETRESET ECONNABORTED ECONNRESET ENOBUFS EISCONN ENOTCONN ESHUTDOWN ETOOMANYREFS ETIMEDOUT ECONNREFUSED EHOSTDOWN EHOSTUNREACH EALREADY EINPROGRESS ESTALE EUCLEAN ENOTNAM ENAVAIL EISNAM EREMOTEIO EDQUOT ENOMEDIUM EMEDIUMTYPE ECANCELED ENOKEY EKEYEXPIRED EKEYREVOKED EKEYREJECTED EOWNERDEAD ENOTRECOVERABLE ERFKILL POLLIN POLLPRI POLLOUT POLLRDNORM POLLRDBAND POLLWRNORM POLLWRBAND POLLMSG POLLREMOVE POLLRDHUP POLLERR POLLHUP POLLNVAL
 syn keyword	pSyscall        accept bind close connect fcntl getsockopt ioctl listen poll read readv recv recvfrom recvmsg send sendmsg sendto setsockopt shutdown socket write writev
diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l
index f24e7292..e7f0c7b2 100644
--- a/gtests/net/packetdrill/lexer.l
+++ b/gtests/net/packetdrill/lexer.l
@@ -159,119 +159,127 @@ v12	({seg}[:]){1,4}[:]{ipv4_addr}
 ipv6_addr ({v0}|{v1}|{v2}|{v3}|{v4}|{v5}|{v6}|{v7}|{v8}|{v9}|{v10}|{v11}|{v12})
 
 %%
-sa_family		return SA_FAMILY;
-sin_port		return SIN_PORT;
-sin_addr		return SIN_ADDR;
-msg_name		return MSG_NAME;
-msg_iov			return MSG_IOV;
-msg_flags		return MSG_FLAGS;
-fd			return FD;
-events			return EVENTS;
-revents			return REVENTS;
-onoff			return ONOFF;
-linger			return LINGER;
-htons			return _HTONS_;
-ipv4			return IPV4;
-ipv6			return IPV6;
-icmp			return ICMP;
-sctp			return SCTP;
-udp			return UDP;
-udplite			return UDPLITE;
-gre			return GRE;
-mpls			return MPLS;
-label			return LABEL;
-tc			return TC;
-ttl			return TTL;
-inet_addr		return INET_ADDR;
-ack			return ACK;
-eol			return EOL;
-ecr			return ECR;
-mss			return MSS;
-mtu			return MTU;
-nop			return NOP;
-sack			return SACK;
-sackOK			return SACKOK;
-TS			return TIMESTAMP;
-FO			return FAST_OPEN;
-val			return VAL;
-win			return WIN;
-wscale			return WSCALE;
-ect01			return ECT01;
-ect0			return ECT0;
-ect1			return ECT1;
-noecn			return NO_ECN;
-ce			return CE;
-[.][.][.]		return ELLIPSIS;
-assoc_value		return ASSOC_VALUE;
-sack_delay		return SACK_DELAY;
-sack_freq		return SACK_FREQ;
-srto_initial		return SRTO_INITIAL;
-srto_max		return SRTO_MAX;
-srto_min		return SRTO_MIN;
-sinit_num_ostreams	return SINIT_NUM_OSTREAMS;
-sinit_max_instreams	return SINIT_MAX_INSTREAMS;
-sinit_max_attempts	return SINIT_MAX_ATTEMPTS;
-sinit_max_init_timeo	return SINIT_MAX_INIT_TIMEO;
-CHUNK			return CHUNK;
-DATA			return DATA;
-INIT			return INIT;
-INIT_ACK		return INIT_ACK;
-SACK			return SACK;
-HEARTBEAT		return HEARTBEAT;
-HEARTBEAT_ACK		return HEARTBEAT_ACK;
-ABORT			return ABORT;
-SHUTDOWN		return SHUTDOWN;
-SHUTDOWN_ACK		return SHUTDOWN_ACK;
-ERROR			return ERROR;
-COOKIE_ECHO		return COOKIE_ECHO;
-COOKIE_ACK		return COOKIE_ACK;
-ECNE			return ECNE;
-CWR			return CWR;
-SHUTDOWN_COMPLETE	return SHUTDOWN_COMPLETE;
-PAD			return PAD;
-type			return TYPE;
-flgs			return FLAGS;
-len			return LEN;
-tag			return TAG;
-a_rwnd			return A_RWND;
-is			return IS;
-os			return OS;
-tsn			return TSN;
-sid			return SID;
-ssn			return SSN;
-ppid			return PPID;
-cum_tsn			return CUM_TSN;
-gaps			return GAPS;
-dups			return DUPS;
-PARAMETER		return PARAMETER;
-HEARTBEAT_INFORMATION	return HEARTBEAT_INFORMATION;
-IPV4_ADDRESS		return IPV4_ADDRESS;
-IPV6_ADDRESS		return IPV6_ADDRESS;
-STATE_COOKIE		return STATE_COOKIE;
-UNRECOGNIZED_PARAMETER	return UNRECOGNIZED_PARAMETER;
-COOKIE_PRESERVATIVE	return COOKIE_PRESERVATIVE;
-HOSTNAME_ADDRESS	return HOSTNAME_ADDRESS;
-SUPPORTED_ADDRESS_TYPES	return SUPPORTED_ADDRESS_TYPES;
-ECN_CAPABLE		return ECN_CAPABLE;
-addr			return ADDR;
-incr			return INCR;
-types			return TYPES;
-params			return PARAMS;
-IPv4			return IPV4_TYPE;
-IPv6			return IPV6_TYPE;
-HOSTNAME		return HOSTNAME_TYPE;
---[a-zA-Z0-9_]+		yylval.string	= option(yytext); return OPTION;
-[-]?[0-9]*[.][0-9]+	yylval.floating	= atof(yytext);   return FLOAT;
-[-]?[0-9]+		yylval.integer	= atoll(yytext);  return INTEGER;
-0x[0-9a-fA-F]+		yylval.integer	= hextol(yytext); return HEX_INTEGER;
-[a-zA-Z0-9_]+		yylval.string	= strdup(yytext); return WORD;
-\"(\\.|[^"])*\"		yylval.string	= quoted(yytext); return STRING;
-\`(\\.|[^`])*\`		yylval.string	= quoted(yytext); return BACK_QUOTED;
-[^ \t\n]		return (int) yytext[0];
-[ \t\n]+		/* ignore whitespace */;
-{cpp_comment}		/* ignore C++-style comment */;
-{c_comment}		/* ignore C-style comment */;
-{code}			yylval.string = code(yytext);   return CODE;
-{ipv4_addr}		yylval.string = strdup(yytext); return IPV4_ADDR;
-{ipv6_addr}		yylval.string = strdup(yytext); return IPV6_ADDR;
+sa_family			return SA_FAMILY;
+sin_port			return SIN_PORT;
+sin_addr			return SIN_ADDR;
+msg_name			return MSG_NAME;
+msg_iov				return MSG_IOV;
+msg_flags			return MSG_FLAGS;
+fd				return FD;
+events				return EVENTS;
+revents				return REVENTS;
+onoff				return ONOFF;
+linger				return LINGER;
+htons				return _HTONS_;
+ipv4				return IPV4;
+ipv6				return IPV6;
+icmp				return ICMP;
+sctp				return SCTP;
+udp				return UDP;
+udplite				return UDPLITE;
+gre				return GRE;
+mpls				return MPLS;
+label				return LABEL;
+tc				return TC;
+ttl				return TTL;
+inet_addr			return INET_ADDR;
+ack				return ACK;
+eol				return EOL;
+ecr				return ECR;
+mss				return MSS;
+mtu				return MTU;
+nop				return NOP;
+sack				return SACK;
+sackOK				return SACKOK;
+TS				return TIMESTAMP;
+FO				return FAST_OPEN;
+val				return VAL;
+win				return WIN;
+wscale				return WSCALE;
+ect01				return ECT01;
+ect0				return ECT0;
+ect1				return ECT1;
+noecn				return NO_ECN;
+ce				return CE;
+[.][.][.]			return ELLIPSIS;
+assoc_value			return ASSOC_VALUE;
+sack_delay			return SACK_DELAY;
+sack_freq			return SACK_FREQ;
+srto_initial			return SRTO_INITIAL;
+srto_max			return SRTO_MAX;
+srto_min			return SRTO_MIN;
+sinit_num_ostreams		return SINIT_NUM_OSTREAMS;
+sinit_max_instreams		return SINIT_MAX_INSTREAMS;
+sinit_max_attempts		return SINIT_MAX_ATTEMPTS;
+sinit_max_init_timeo		return SINIT_MAX_INIT_TIMEO;
+sstat_state			return SSTAT_STATE;
+sstat_rwnd			return SSTAT_RWND;
+sstat_unackdata			return SSTAT_UNACKDATA;
+sstat_penddata			return SSTAT_PENDDATA;
+sstat_instrms			return SSTAT_INSTRMS;
+sstat_outstrms			return SSTAT_OUTSTRMS;
+sstat_fragmentation_point	return SSTAT_FRAGMENTATION_POINT;
+sstat_primary			return SSTAT_PRIMARY;
+CHUNK				return CHUNK;
+DATA				return DATA;
+INIT				return INIT;
+INIT_ACK			return INIT_ACK;
+SACK				return SACK;
+HEARTBEAT			return HEARTBEAT;
+HEARTBEAT_ACK			return HEARTBEAT_ACK;
+ABORT				return ABORT;
+SHUTDOWN			return SHUTDOWN;
+SHUTDOWN_ACK			return SHUTDOWN_ACK;
+ERROR				return ERROR;
+COOKIE_ECHO			return COOKIE_ECHO;
+COOKIE_ACK			return COOKIE_ACK;
+ECNE				return ECNE;
+CWR				return CWR;
+SHUTDOWN_COMPLETE		return SHUTDOWN_COMPLETE;
+PAD				return PAD;
+type				return TYPE;
+flgs				return FLAGS;
+len				return LEN;
+tag				return TAG;
+a_rwnd				return A_RWND;
+is				return IS;
+os				return OS;
+tsn				return TSN;
+sid				return SID;
+ssn				return SSN;
+ppid				return PPID;
+cum_tsn				return CUM_TSN;
+gaps				return GAPS;
+dups				return DUPS;
+PARAMETER			return PARAMETER;
+HEARTBEAT_INFORMATION		return HEARTBEAT_INFORMATION;
+IPV4_ADDRESS			return IPV4_ADDRESS;
+IPV6_ADDRESS			return IPV6_ADDRESS;
+STATE_COOKIE			return STATE_COOKIE;
+UNRECOGNIZED_PARAMETER		return UNRECOGNIZED_PARAMETER;
+COOKIE_PRESERVATIVE		return COOKIE_PRESERVATIVE;
+HOSTNAME_ADDRESS		return HOSTNAME_ADDRESS;
+SUPPORTED_ADDRESS_TYPES		return SUPPORTED_ADDRESS_TYPES;
+ECN_CAPABLE			return ECN_CAPABLE;
+addr				return ADDR;
+incr				return INCR;
+types				return TYPES;
+params				return PARAMS;
+IPv4				return IPV4_TYPE;
+IPv6				return IPV6_TYPE;
+HOSTNAME			return HOSTNAME_TYPE;
+--[a-zA-Z0-9_]+			yylval.string	= option(yytext); return OPTION;
+[-]?[0-9]*[.][0-9]+		yylval.floating	= atof(yytext);   return FLOAT;
+[-]?[0-9]+			yylval.integer	= atoll(yytext);  return INTEGER;
+0x[0-9a-fA-F]+			yylval.integer	= hextol(yytext); return HEX_INTEGER;
+[a-zA-Z0-9_]+			yylval.string	= strdup(yytext); return WORD;
+\"(\\.|[^"])*\"			yylval.string	= quoted(yytext); return STRING;
+\`(\\.|[^`])*\`			yylval.string	= quoted(yytext); return BACK_QUOTED;
+[^ \t\n]			return (int) yytext[0];
+[ \t\n]+			/* ignore whitespace */;
+{cpp_comment}			/* ignore C++-style comment */;
+{c_comment}			/* ignore C-style comment */;
+{code}				yylval.string = code(yytext);   return CODE;
+{ipv4_addr}			yylval.string = strdup(yytext); return IPV4_ADDR;
+{ipv6_addr}			yylval.string = strdup(yytext); return IPV6_ADDR;
 %%
diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index d70fa720..69a84309 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -503,6 +503,9 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %token <reserved> SINIT_MAX_INIT_TIMEO
 %token <reserved> ASSOC_VALUE
 %token <reserved> SACK_DELAY SACK_FREQ
+%token <reserved> SSTAT_STATE SSTAT_RWND SSTAT_UNACKDATA SSTAT_PENDDATA
+%token <reserved> SSTAT_INSTRMS SSTAT_OUTSTRMS SSTAT_FRAGMENTATION_POINT
+%token <reserved> SSTAT_PRIMARY;
 %token <reserved> CHUNK DATA INIT INIT_ACK HEARTBEAT HEARTBEAT_ACK ABORT
 %token <reserved> SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECNE CWR
 %token <reserved> SHUTDOWN_COMPLETE PAD
@@ -550,6 +553,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string,
 %type <expression> decimal_integer hex_integer
 %type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents linger
 %type <expression> sctp_rtoinfo sctp_initmsg sctp_assocval sctp_sackinfo
+%type <expression> sctp_status
 %type <errno_info> opt_errno
 %type <chunk_list> sctp_chunk_list_spec
 %type <chunk_list_item> sctp_chunk_spec
@@ -1921,6 +1925,9 @@ expression
 | sctp_sackinfo     {
 	$$ = $1;
 }
+| sctp_status       {
+	$$ = $1;
+}
 ;
 
 decimal_integer
@@ -2127,6 +2134,43 @@ sctp_sackinfo
 }
 ;
 
+sctp_status
+: '{' SSTAT_STATE '=' INTEGER ',' SSTAT_RWND '=' INTEGER ',' SSTAT_UNACKDATA '=' INTEGER ',' SSTAT_PENDDATA '=' INTEGER ',' SSTAT_INSTRMS '=' INTEGER ',' SSTAT_OUTSTRMS '=' INTEGER ',' SSTAT_FRAGMENTATION_POINT '=' INTEGER ',' SSTAT_PRIMARY '=' ELLIPSIS '}' {
+#ifdef SCTP_INITMSG
+	$$ = new_expression(EXPR_SCTP_STATUS);
+	if (!is_valid_s32($4)) {
+		semantic_error("sstat_state out of range");
+	}
+	$$->value.sctp_status.sstat_state = $4;
+	if (!is_valid_u32($8)) {
+		semantic_error("sstat_rwnd out of range");
+	}
+	$$->value.sctp_status.sstat_rwnd = $8;
+	if (!is_valid_u16($12)) {
+		semantic_error("sstat_unackdata out of range");
+	}
+	$$->value.sctp_status.sstat_unackdata = $12;
+	if (!is_valid_u16($16)) {
+		semantic_error("sstat_penddata out of range");
+	}
+	$$->value.sctp_status.sstat_penddata = $16;
+	if (!is_valid_u16($20)) {
+		semantic_error("sstat_instrms out of range");
+	}
+	$$->value.sctp_status.sstat_instrms = $20;
+	if (!is_valid_u16($24)) {
+		semantic_error("sstat_outstrms out of range");
+	}
+	$$->value.sctp_status.sstat_outstrms = $24;
+	if (!is_valid_u32($28)) {
+		semantic_error("sstat_fragmentation_point out of range");
+	}
+	$$->value.sctp_status.sstat_fragmentation_point = $28;
+#else
+	$$ = NULL;
+#endif
+}
+
 opt_errno
 :                   { $$ = NULL; }
 | WORD note         {
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 0372ceb9..a60b0662 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -1652,6 +1652,10 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 #ifdef SCTP_DELAYED_SACK
 	} else if (val_expression->type == EXPR_SCTP_SACKINFO) {
 		optval = &val_expression->value.sctp_sack_info;
+#endif
+#ifdef SCTP_STATUS
+	} else if (val_expression->type == EXPR_SCTP_STATUS) {
+		optval = &val_expression->value.sctp_status;
 #endif
 	} else {
 		asprintf(error, "unsupported setsockopt value type: %s",
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index d0e9dcd1..c4fdb4b2 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -76,6 +76,9 @@ struct expression_type_entry expression_type_table[] = {
 #endif
 #ifdef SCTP_DELAYED_SACK
 	{ EXPR_SCTP_SACKINFO,        "sctp_sackinfo"},
+#endif
+#ifdef SCTP_STATUS
+	{ EXPR_SCTP_STATUS,           "sctp_status"},
 #endif
 	{ NUM_EXPR_TYPES,            NULL}
 };
@@ -294,6 +297,9 @@ void free_expression(struct expression *expression)
 #endif
 #ifdef SCTP_DELAYED_SACK
 	case EXPR_SCTP_SACKINFO:
+#endif
+#ifdef SCTP_STATUS
+	case EXPR_SCTP_STATUS:
 #endif
 		break;
 	case EXPR_WORD:
@@ -528,6 +534,12 @@ static int evaluate(struct expression *in,
 		memcpy(&out->value.sctp_sack_info, &in->value.sctp_sack_info,
 		       sizeof(in->value.sctp_sack_info));
 		break;
+#endif
+#ifdef SCTP_STATUS
+	case EXPR_SCTP_STATUS:	/* copy as-is */
+		memcpy(&out->value.sctp_status, &in->value.sctp_status,
+		       sizeof(in->value.sctp_status));
+		break;
 #endif
 	case EXPR_WORD:
 		out->type = EXPR_INTEGER;
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index cab9a22d..a2b2e46b 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -57,6 +57,9 @@ enum expression_t {
 #ifdef SCTP_DELAYED_SACK
 	EXPR_SCTP_SACKINFO,	  /* struct sctp_sack_info for
 				   * SCTP_DELAYED_SACK */
+#endif
+#ifdef SCTP_STATUS
+	EXPR_SCTP_STATUS,	  /* struct sctp_status for SCTP_STATUS */
 #endif
 	NUM_EXPR_TYPES,
 };
@@ -88,6 +91,9 @@ struct expression {
 #endif
 #ifdef SCTP_DELAYED_SACK
 		struct sctp_sack_info sctp_sack_info;
+#endif
+#ifdef SCTP_STATUS
+		struct sctp_status sctp_status;
 #endif
 	} value;
 	const char *format;	/* the printf format for printing the value */
diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c
index c760b465..9e4e8093 100644
--- a/gtests/net/packetdrill/symbols_freebsd.c
+++ b/gtests/net/packetdrill/symbols_freebsd.c
@@ -85,6 +85,17 @@ struct int_symbol platform_symbols_table[] = {
 	{ SCTP_MAXSEG,                      "SCTP_MAXSEG"                     },
 	{ SCTP_DELAYED_SACK,                "SCTP_DELAYED_SACK"               },
 	{ SCTP_MAX_BURST,                   "SCTP_MAX_BURST"                  },
+	{ SCTP_STATUS,                      "SCTP_STATUS"                     },
+	{ SCTP_CLOSED,                      "SCTP_CLOSED"                     },
+	{ SCTP_BOUND,                       "SCTP_BOUND"                      },
+	{ SCTP_LISTEN,                      "SCTP_LISTEN"                     },
+	{ SCTP_COOKIE_WAIT,                 "SCTP_COOKIE_WAIT"                },
+	{ SCTP_COOKIE_ECHOED,               "SCTP_COOKIE_ECHOED"              },
+	{ SCTP_ESTABLISHED,                 "SCTP_ESTABLISHED"                },
+	{ SCTP_SHUTDOWN_SENT,               "SCTP_SHUTDOWN_SENT"              },
+	{ SCTP_SHUTDOWN_RECEIVED,           "SCTP_SHUTDOWN_RECEIVED"          },
+	{ SCTP_SHUTDOWN_ACK_SENT,           "SCTP_SHUTDOWN_ACK_SENT"          },
+	{ SCTP_SHUTDOWN_PENDING,            "SCTP_SHUTDOWN_PENDING"           },
 
 	/* /usr/include/netinet/tcp.h */
 	{ TCP_NODELAY,                      "TCP_NODELAY"                     },
diff --git a/gtests/net/packetdrill/symbols_linux.c b/gtests/net/packetdrill/symbols_linux.c
index 518c5322..5e04beeb 100644
--- a/gtests/net/packetdrill/symbols_linux.c
+++ b/gtests/net/packetdrill/symbols_linux.c
@@ -118,6 +118,19 @@ struct int_symbol platform_symbols_table[] = {
 #ifdef SCTP_MAX_BURST
 	{ SCTP_MAX_BURST,                   "SCTP_MAX_BURST"                  },
 #endif
+#ifdef SCTP_STATUS
+	{ SCTP_STATUS,                      "SCTP_STATUS"                     },
+#endif
+	{ SCTP_CLOSED,                      "SCTP_CLOSED"                     },
+	{ SCTP_BOUND,                       "SCTP_BOUND"                      },
+	{ SCTP_LISTEN,                      "SCTP_LISTEN"                     },
+	{ SCTP_COOKIE_WAIT,                 "SCTP_COOKIE_WAIT"                },
+	{ SCTP_COOKIE_ECHOED,               "SCTP_COOKIE_ECHOED"              },
+	{ SCTP_ESTABLISHED,                 "SCTP_ESTABLISHED"                },
+	{ SCTP_SHUTDOWN_SENT,               "SCTP_SHUTDOWN_SENT"              },
+	{ SCTP_SHUTDOWN_RECEIVED,           "SCTP_SHUTDOWN_RECEIVED"          },
+	{ SCTP_SHUTDOWN_ACK_SENT,           "SCTP_SHUTDOWN_ACK_SENT"          },
+	{ SCTP_SHUTDOWN_PENDING,            "SCTP_SHUTDOWN_PENDING"           },
 
 	{ TCP_NODELAY,                      "TCP_NODELAY"                     },
 	{ TCP_MAXSEG,                       "TCP_MAXSEG"                      },
diff --git a/gtests/net/packetdrill/types.h b/gtests/net/packetdrill/types.h
index 6ccfbe44..a9c6055e 100644
--- a/gtests/net/packetdrill/types.h
+++ b/gtests/net/packetdrill/types.h
@@ -197,6 +197,21 @@ static inline bool is_valid_u32(s64 x)
 	return (x >= 0) && (x <= UINT_MAX);
 }
 
+static inline bool is_valid_s8(s64 x)
+{
+	return (x >= CHAR_MIN) && (x <= CHAR_MAX);
+}
+
+static inline bool is_valid_s16(s64 x)
+{
+	return (x >= SHRT_MIN) && (x <= SHRT_MAX);
+}
+
+static inline bool is_valid_s32(s64 x)
+{
+	return (x >= INT_MIN) && (x <= INT_MAX);
+}
+
 static inline s64 max(s64 a, s64 b)
 {
 	return (a > b) ? a : b;
-- 
GitLab