diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 68793dc9b124253b90d6e7a8368e5eb622330fed..7081003d1dbfcd2f3b6dc3f9399872044957b164 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -3998,6 +3998,62 @@ static int get_sockaddr_from_list(struct expression *expr, size_t *addr_size, st } #endif +static int syscall_sctp_send(struct state *state, struct syscall_spec *syscall, + struct expression_list *args, + char **error) +{ +#if defined(__FreeBSD__) || defined(linux) + int script_fd, live_fd, flags, result; + size_t len; + void *msg; + struct expression *len_expr, *info_expr; + struct sctp_sndrcvinfo info; + + if (check_arg_count(args, 5, error)) + return STATUS_ERR; + if (s32_arg(args, 0, &script_fd, error)) + return STATUS_ERR; + if (to_live_fd(state, script_fd, &live_fd, error)) + return STATUS_ERR; + if (ellipsis_arg(args, 1, error)) + return STATUS_ERR; + len_expr = get_arg(args, 2, error); + if (get_u32(len_expr, &len, error)) { + return STATUS_ERR; + } + info_expr = get_arg(args, 3, error); + if (check_type(info_expr, EXPR_SCTP_SNDRCVINFO, error)) { + return STATUS_ERR; + } + if (parse_expression_to_sctp_sndrcvinfo(info_expr, &info, true, error)) { + return STATUS_ERR; + } + if (s32_arg(args, 4, &flags, error)) { + return STATUS_ERR; + } + msg = calloc(len, 1); + assert(msg != NULL); + + begin_syscall(state, syscall); + + result = sctp_send(live_fd, msg, len, &info, flags); + free(msg); + + if (end_syscall(state, syscall, CHECK_EXACT, result, error)) { + return STATUS_ERR; + } + if (check_sctp_sndrcvinfo(info_expr->value.sctp_sndrcvinfo, &info, error)) { + return STATUS_ERR; + } + + return STATUS_OK; +#else + asprintf(error, "sctp_send is not supported"); + return STATUS_ERR; +#endif +} + + static int syscall_sctp_sendv(struct state *state, struct syscall_spec *syscall, struct expression_list *args, char **error) @@ -4909,6 +4965,7 @@ struct system_call_entry system_call_table[] = { {"getsockopt", syscall_getsockopt}, {"setsockopt", syscall_setsockopt}, {"poll", syscall_poll}, + {"sctp_send", syscall_sctp_send}, {"sctp_sendmsg", syscall_sctp_sendmsg}, {"sctp_recvmsg", syscall_sctp_recvmsg}, {"sctp_sendv", syscall_sctp_sendv}, diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_send.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_send.pkt new file mode 100644 index 0000000000000000000000000000000000000000..dd3e13911825b78a56cb92b365c497f847661f3b --- /dev/null +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_send.pkt @@ -0,0 +1,46 @@ +--tolerance_usecs=100000 + + 0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 ++0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) ++0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 ++0.0 bind(3, ..., ...) = 0 +// Check the handshake with an empty(!) cookie ++0.1 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) ++0.0 > sctp: INIT[flgs=0, tag=1, a_rwnd=..., os=..., is=..., tsn=1, ...] ++0.1 < sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=1500, os=16, is=16, tsn=1, STATE_COOKIE[len=4, val=...]] ++0.0 > sctp: COOKIE_ECHO[flgs=0, len=4, val=...] ++0.1 < sctp: COOKIE_ACK[flgs=0] ++0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 +//sendmsg(sd, msghdr, flags) + ++0.0 setsockopt(3, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, {spp_address={sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}, +spp_hbinterval=0, spp_pathmaxrxt=8, spp_pathmtu=1468, spp_flags=SPP_HB_DISABLE, spp_ipv6_flowlabel=0, spp_dscp=0}, 152) = 0 + ++1.0 sctp_send(3, ..., 1000, {sinfo_stream=3, + sinfo_ssn=3, + sinfo_flags=0, + sinfo_ppid=htonl(7), + sinfo_context=0, + sinfo_timetolive=0, + sinfo_tsn=1, + sinfo_cumtsn=6, + sinfo_assoc_id=3}, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=3, ssn=0, ppid=7] ++0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]] + ++1.0 sctp_send(3, ..., 1000, {sinfo_stream=3, + sinfo_ssn=3, + sinfo_flags=0, + sinfo_ppid=htonl(1234), + sinfo_context=0, + sinfo_timetolive=0, + sinfo_tsn=2, + sinfo_cumtsn=2, + sinfo_assoc_id=3}, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=2, sid=3, ssn=1, ppid=1234] ++0.0 < sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=1500, gaps=[], dups=[]] + ++0.0 close(3) = 0 ++0.0 > sctp: SHUTDOWN[flgs=0, cum_tsn=0] ++0.1 < sctp: SHUTDOWN_ACK[flgs=0] ++0.0 > sctp: SHUTDOWN_COMPLETE[flgs=0]