diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index a60b0662095eec5e2011cfea04d9d94aa045afea..5c492145b334e146725f0c56e02aecf5569184a8 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -1560,8 +1560,10 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, struct expression_list *args, char **error) { int script_fd, live_fd, level, optname, result; - s32 script_optval, live_optval, script_optlen; - socklen_t live_optlen = sizeof(live_optval); + s32 script_optval, script_optlen, expected; + void *live_optval; + socklen_t live_optlen; + struct expression *val_expression; if (check_arg_count(args, 5, error)) return STATUS_ERR; if (s32_arg(args, 0, &script_fd, error)) @@ -1572,37 +1574,103 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, return STATUS_ERR; if (s32_arg(args, 2, &optname, error)) return STATUS_ERR; - if (s32_bracketed_arg(args, 3, &script_optval, error)) - return STATUS_ERR; if (s32_bracketed_arg(args, 4, &script_optlen, error)) return STATUS_ERR; - if (script_optlen != 4) { - asprintf(error, "Unsupported getsockopt optlen: %d", - (int)script_optlen); + if (get_s32(syscall->result, &expected, error)) return STATUS_ERR; + val_expression = get_arg(args, 3, error); + if (val_expression == NULL) { + return STATUS_ERR; + } else if (val_expression->type == EXPR_LINGER) { + live_optval = (void *) malloc(sizeof(val_expression->value.linger)); + live_optlen = sizeof(val_expression->value.linger); +#ifdef SCTP_RTOINFO + } else if (val_expression->type == EXPR_SCTP_RTOINFO) { + live_optval = (void*) malloc(sizeof(val_expression->value.sctp_rtoinfo)); + live_optlen = sizeof(val_expression->value.sctp_rtoinfo); +#endif +#ifdef SCTP_STATUS + } else if (val_expression->type == EXPR_SCTP_STATUS) { + live_optval = (void*) malloc(sizeof(val_expression->value.sctp_status)); + live_optlen = sizeof(val_expression->value.sctp_status); + ((struct sctp_status*) live_optval)->sstat_assoc_id = val_expression->value.sctp_status.sstat_assoc_id; +#endif + }else { + s32_bracketed_arg(args, 3, &script_optval, error); + live_optval = (void *) malloc(sizeof(int)); + live_optlen = sizeof(int); } begin_syscall(state, syscall); - - result = getsockopt(live_fd, level, optname, - &live_optval, &live_optlen); - - if (end_syscall(state, syscall, CHECK_EXACT, result, error)) - return STATUS_ERR; - - if ((int)live_optlen != script_optlen) { - asprintf(error, - "Bad getsockopt optlen: expected: %d actual: %d", - (int)script_optlen, (int)live_optlen); + + result = getsockopt(live_fd, level, optname, live_optval, &live_optlen); + if (end_syscall(state, syscall, CHECK_NON_NEGATIVE, result, error)) { return STATUS_ERR; } - if (live_optval != script_optval) { - asprintf(error, - "Bad getsockopt optval: expected: %d actual: %d", - (int)script_optval, (int)live_optval); + + if (live_optlen != script_optlen) { + asprintf(error, "Bad getsockopt optlen: expected: %d actual: %d", (int)script_optlen, (int)live_optlen); return STATUS_ERR; } + if (val_expression->type == EXPR_LINGER) { + struct linger *ling = live_optval; + if (ling->l_onoff != val_expression->value.linger.l_onoff){ + asprintf(error, "Bad getsockopt Linger onoff: expected: %d actual: %u", (int)val_expression->value.linger.l_onoff, (int)ling->l_onoff); + return STATUS_ERR; + } + if (ling->l_linger != val_expression->value.linger.l_linger){ + asprintf(error, "Bad getsockopt Linger Value: expected: %d actual: %d", (int)val_expression->value.linger.l_linger, (int)ling->l_linger); + return STATUS_ERR; + } +#ifdef SCTP_RTOINFO + } else if (val_expression->type == EXPR_SCTP_RTOINFO) { + struct sctp_rtoinfo *rtoinfo = live_optval; + if (rtoinfo->srto_initial != val_expression->value.sctp_rtoinfo.srto_initial){ + asprintf(error, "Bad getsockopt SCTP_RTOINFO initial: expected: %d actual: %d", (int)val_expression->value.sctp_rtoinfo.srto_initial, (int)rtoinfo->srto_initial); + return STATUS_ERR; + } else if (rtoinfo->srto_max != val_expression->value.sctp_rtoinfo.srto_max){ + asprintf(error, "Bad getsockopt SCTP_RTOINFO SRTO_MAX: expected: %d actual: %d", (int)val_expression->value.sctp_rtoinfo.srto_max, (int)rtoinfo->srto_max); + return STATUS_ERR; + } else if (rtoinfo->srto_min != val_expression->value.sctp_rtoinfo.srto_min){ + asprintf(error, "Bad getsockopt SCTP_RTOINFO SRTO_MIN: expected: %d actual: %d", (int)val_expression->value.sctp_rtoinfo.srto_min, (int)rtoinfo->srto_min); + return STATUS_ERR; + } +#endif +#ifdef SCTP_STATUS + } else if (val_expression->type == EXPR_SCTP_STATUS) { + struct sctp_status *live_val = live_optval; + struct sctp_status *expected_val = &(val_expression->value.sctp_status); + if (live_val->sstat_state != expected_val->sstat_state) { + asprintf(error, "Bad getsockopt SCTP_STATUS state: expected: %d actual: %d ", expected_val->sstat_state, live_val->sstat_state); + return STATUS_ERR; + } else if (live_val->sstat_rwnd != expected_val->sstat_rwnd) { + asprintf(error, "Bad getsockopt SCTP_STATUS rwnd: expected: %d actual: %d ", (int) expected_val->sstat_rwnd, (int) live_val->sstat_rwnd); + return STATUS_ERR; + } else if (live_val->sstat_unackdata != expected_val->sstat_unackdata) { + asprintf(error, "Bad getsockopt SCTP_STATUS unackdata: expected: %d actual: %d", (int) expected_val->sstat_unackdata, (int) live_val->sstat_unackdata); + return STATUS_ERR; + } else if (live_val->sstat_penddata != expected_val->sstat_penddata) { + asprintf(error, "Bad getsockopt SCTP_STATUS penddata: expected: %d actual: %d", (int) expected_val->sstat_penddata, (int) live_val->sstat_penddata); + return STATUS_ERR; + } else if (live_val->sstat_instrms != expected_val->sstat_instrms) { + asprintf(error, "Bad getsockopt SCTP_STATUS instreams: expected: %d actual: %d", (int) expected_val->sstat_instrms, (int) live_val->sstat_instrms); + return STATUS_ERR; + } else if (live_val->sstat_outstrms != expected_val->sstat_outstrms) { + asprintf(error, "Bad getsockopt SCTP_STATUS outstreams: expected: %d actual: %d", (int) expected_val->sstat_outstrms, (int) live_val->sstat_outstrms); + return STATUS_ERR; + } else if (live_val->sstat_fragmentation_point != expected_val->sstat_fragmentation_point){ + asprintf(error, "Bad getsockopt SCTP_STATUS fragmentation point: expected: %d actual: %d", (int) expected_val->sstat_fragmentation_point, (int) live_val->sstat_fragmentation_point); + return STATUS_ERR; + } +#endif + }else{ + if (*(int*)live_optval != script_optval) { + asprintf(error, "Bad getsockopt optval: expected: %d actual: %d", (int)script_optval, *(int*)live_optval); + return STATUS_ERR; + } + + } return STATUS_OK; } diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt new file mode 100644 index 0000000000000000000000000000000000000000..3310fd898266cb57a1efbbe9445c2d0775544a8e --- /dev/null +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt @@ -0,0 +1,24 @@ +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 +// 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=1, is=1, 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 + ++0 setsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=50}, 16) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_RTOINFO, {srto_initial=100, srto_max=200, srto_min=50}, [16]) = 0 + ++0 getsockopt(3, IPPROTO_SCTP, SCTP_STATUS, {sstat_state=8, sstat_rwnd=1500, sstat_unackdata=0, sstat_penddata=0, sstat_instrms=1, sstat_outstrms=1, + sstat_fragmentation_point=1452, sstat_primary=...}, [176])= 0 + ++0 setsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=1, linger=30}, 8) = 0 ++0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=128, linger=30}, [8]) = 0 + + ++0 close(3) = 0 +