diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 694876727fc3a75743a4d2a8fd038a06c3226a15..357e47227b02cf926f6e9e47279c333474a58b20 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -265,6 +265,19 @@ sendv_flags return SENDV_FLAGS; sendv_sndinfo return SENDV_SNDINFO; sendv_prinfo return SENDV_PRINFO; sendv_authinfo return SENDV_AUTHINFO; +rcv_sid return RCV_SID; +rcv_ssn return RCV_SSN; +rcv_flags return RCV_FLAGS; +rcv_ppid return RCV_PPID; +rcv_tsn return RCV_TSN; +rcv_cumtsn return RCV_CUMTSN; +rcv_context return RCV_CONTEXT; +nxt_sid return NXT_SID; +nxt_flags return NXT_FLAGS; +nxt_ppid return NXT_PPID; +nxt_length return NXT_LENGTH; +recvv_rcvinfo return RECVV_RCVINFO; +recvv_nxtinfo return RECVV_NXTINFO; CHUNK return CHUNK; DATA return DATA; INIT return INIT; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 1b74def5f3a137a5596d84b89fef92e0245629f2..634e6487ca851432dcdfa00aa68661357d846eba 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -544,6 +544,9 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> SINFO_TIMETOLIVE SINFO_TSN SINFO_CUMTSN %token <reserved> PR_POLICY PR_VALUE AUTH_KEYNUMBER SENDV_FLAGS SENDV_SNDINFO %token <reserved> SENDV_PRINFO SENDV_AUTHINFO +%token <reserved> RCV_SID RCV_SSN RCV_FLAGS RCV_PPID RCV_TSN RCV_CUMTSN RCV_CONTEXT +%token <reserved> NXT_SID NXT_FLAGS NXT_PPID NXT_LENGTH +%token <reserved> RECVV_RCVINFO RECVV_NXTINFO %token <floating> FLOAT %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR @@ -597,6 +600,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> sctp_sndrcvinfo sinfo_stream sinfo_ssn sinfo_flags sinfo_ppid sinfo_context %type <expression> sinfo_timetolive sinfo_tsn sinfo_cumtsn %type <expression> sctp_prinfo sctp_authinfo pr_policy sctp_sendv_spa +%type <expression> sctp_rcvinfo rcv_sid rcv_ssn rcv_flags rcv_ppid rcv_tsn rcv_cumtsn rcv_context +%type <expression> sctp_nxtinfo nxt_sid nxt_flags nxt_ppid nxt_length sctp_recvv_rn %type <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec %type <chunk_list_item> sctp_chunk_spec @@ -2472,6 +2477,15 @@ expression | sctp_sendv_spa { $$ = $1; } +| sctp_rcvinfo { + $$ = $1; +} +| sctp_nxtinfo { + $$ = $1; +} +| sctp_recvv_rn { + $$ = $1; +} | null { $$ = $1; } @@ -3255,6 +3269,91 @@ sctp_sndrcvinfo $$->value.sctp_sndrcvinfo->sinfo_cumtsn = $16; }; +rcv_sid +: RCV_SID '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("rcv_sid out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| RCV_SID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +rcv_ssn +: RCV_SSN '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("rcv_ssn out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| RCV_SSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +rcv_flags +: RCV_FLAGS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("rcv_flags out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| RCV_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +rcv_ppid +: RCV_PPID '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("sinfo_cumtsn out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| RCV_PPID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +rcv_tsn +: RCV_TSN '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("rcv_tsn out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| RCV_TSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +rcv_cumtsn +: RCV_CUMTSN '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("rcv_cumtsn out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| RCV_CUMTSN '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +rcv_context +: RCV_CONTEXT '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("rcv_context out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| RCV_CONTEXT '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + + +sctp_rcvinfo +: '{' rcv_sid ',' rcv_ssn ',' rcv_flags ',' rcv_ppid ',' rcv_tsn ',' rcv_cumtsn ',' rcv_context '}' { + $$ = new_expression(EXPR_SCTP_RCVINFO); + $$->value.sctp_rcvinfo = calloc(1, sizeof(struct sctp_rcvinfo_expr)); + $$->value.sctp_rcvinfo->rcv_sid = $2; + $$->value.sctp_rcvinfo->rcv_ssn = $4; + $$->value.sctp_rcvinfo->rcv_flags = $6; + $$->value.sctp_rcvinfo->rcv_ppid = $8; + $$->value.sctp_rcvinfo->rcv_tsn = $10; + $$->value.sctp_rcvinfo->rcv_cumtsn = $12; + $$->value.sctp_rcvinfo->rcv_context = $14; +} +; + pr_policy : PR_POLICY '=' WORD { $$ = new_expression(EXPR_WORD); @@ -3301,6 +3400,66 @@ sctp_sendv_spa } ; +nxt_sid +: NXT_SID '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("nxt_sid out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| NXT_SID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +nxt_flags +: NXT_FLAGS '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("nxt_flags out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| NXT_FLAGS '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +nxt_ppid +: NXT_PPID '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("nxt_ppid out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| NXT_PPID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +nxt_length +: NXT_LENGTH '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("nxt_length out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| NXT_LENGTH '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +sctp_nxtinfo +: '{' nxt_sid ',' nxt_flags ',' nxt_ppid ',' nxt_length '}' { + $$ = new_expression(EXPR_SCTP_NXTINFO); + $$->value.sctp_sendv_spa = calloc(1, sizeof(struct sctp_nxtinfo_expr)); + $$->value.sctp_nxtinfo->nxt_sid = $2; + $$->value.sctp_nxtinfo->nxt_flags = $4; + $$->value.sctp_nxtinfo->nxt_ppid = $6; + $$->value.sctp_nxtinfo->nxt_length = $8; +} +; + +sctp_recvv_rn +: '{' RECVV_RCVINFO '=' sctp_rcvinfo ',' RECVV_NXTINFO '=' sctp_nxtinfo '}' { + $$ = new_expression(EXPR_SCTP_RECVV_RN); + $$->value.sctp_sendv_spa = calloc(1, sizeof(struct sctp_recvv_rn_expr)); + $$->value.sctp_recvv_rn->recvv_rcvinfo = $4; + $$->value.sctp_recvv_rn->recvv_nxtinfo = $8; +} +; + opt_errno : { $$ = NULL; } | WORD note { diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 32bc900fccd9256c1580ef8cc625d3b0bc3e9fb9..f82e14f50ac20867c66b0ebc380f9749520d990d 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -3158,67 +3158,30 @@ static int check_sctp_sndrcvinfo(struct sctp_sndrcvinfo_expr *expr, } #endif -static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscall, - struct expression_list *args, - char **error) -{ -#if defined(__FreeBSD__) || defined(__Linux__) - int script_fd, live_fd, live_msg_flags, result; - void *msg; - u32 len; - struct sockaddr live_from; - socklen_t live_fromlen; - struct sctp_sndrcvinfo live_sinfo; - struct expression *len_expr, *script_sinfo_expr, *script_msg_flags_expr; - struct expression *script_fromlen_expr, *script_from_expr; +static int check_sockaddr(struct expression *sockaddr_expr, struct sockaddr *live_addr, char **error) { - if (check_arg_count(args, 7, 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; - - msg = calloc(len, 1); - assert(msg != NULL); - - begin_syscall(state, syscall); - result = sctp_recvmsg(live_fd, msg, len, (struct sockaddr*) &live_from, - &live_fromlen, &live_sinfo, &live_msg_flags); - free(msg); - - if (end_syscall(state, syscall, CHECK_EXACT, result, error)) { - return STATUS_ERR; - } - - script_from_expr = get_arg(args, 3, error); - if (script_from_expr->type != EXPR_ELLIPSIS) { + if (sockaddr_expr->type != EXPR_ELLIPSIS) { struct sockaddr *script_addr; - if (script_from_expr->type == EXPR_SOCKET_ADDRESS_IPV4) { - script_addr = (struct sockaddr*)script_from_expr->value.socket_address_ipv4; - } else if( script_from_expr->type == EXPR_SOCKET_ADDRESS_IPV6) { - script_addr = (struct sockaddr*)script_from_expr->value.socket_address_ipv6; + if (sockaddr_expr->type == EXPR_SOCKET_ADDRESS_IPV4) { + script_addr = (struct sockaddr*)sockaddr_expr->value.socket_address_ipv4; + } else if (sockaddr_expr->type == EXPR_SOCKET_ADDRESS_IPV6) { + script_addr = (struct sockaddr*)sockaddr_expr->value.socket_address_ipv6; } else { - asprintf(error, "sctp_recvmsg fromlen: can't check sctp_recvmsg from"); + asprintf(error, "Bad type for sockaddr"); return STATUS_ERR; } - if (script_addr->sa_family != live_from.sa_family) { - asprintf(error, "sctp_recvmsg from.sa_family: expected: %d actual: %d", - script_addr->sa_family, live_from.sa_family); + if (script_addr->sa_family != live_addr->sa_family) { + asprintf(error, "sockaddr sa_family expected: %d actual: %d", + script_addr->sa_family, live_addr->sa_family); return STATUS_ERR; } switch(script_addr->sa_family) { case AF_INET: { struct sockaddr_in *script_sockaddr = (struct sockaddr_in*)script_addr; - struct sockaddr_in *live_sockaddr = (struct sockaddr_in*)&live_from; + struct sockaddr_in *live_sockaddr = (struct sockaddr_in*)live_addr; if (live_sockaddr->sin_port != script_sockaddr->sin_port) { - asprintf(error, "sctp_recvmsg from.sinport. expected: %d actual %d", + asprintf(error, "sockaddr_in from.sinport. expected: %d actual %d", ntohs(script_sockaddr->sin_port), ntohs(live_sockaddr->sin_port)); return STATUS_ERR; } @@ -3226,7 +3189,7 @@ static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscal int len = strnlen(inet_ntoa(script_sockaddr->sin_addr), 16); char *expected_addr = malloc(sizeof(char) * len); memcpy(expected_addr, inet_ntoa(script_sockaddr->sin_addr), len); - asprintf(error, "sctp_recvmsg from.sin_addr. expected: %s actual %s", + asprintf(error, "sockaddr_in from.sin_addr. expected: %s actual %s", expected_addr, inet_ntoa(live_sockaddr->sin_addr)); free(expected_addr); return STATUS_ERR; @@ -3236,9 +3199,9 @@ static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscal case AF_INET6: { struct sockaddr_in6 *script_sockaddr = (struct sockaddr_in6*)script_addr; - struct sockaddr_in6 *live_sockaddr = (struct sockaddr_in6*)&live_from; + struct sockaddr_in6 *live_sockaddr = (struct sockaddr_in6*)live_addr; if (live_sockaddr->sin6_port != script_sockaddr->sin6_port) { - asprintf(error, "sctp_recvmsg from.sinport. expected: %d actual %d", + asprintf(error, "sockaddr_in6 from.sinport. expected: %d actual %d", ntohs(script_sockaddr->sin6_port), ntohs(live_sockaddr->sin6_port)); return STATUS_ERR; } @@ -3247,16 +3210,60 @@ static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscal char live_addr[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &script_sockaddr->sin6_addr, expected_addr, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &live_sockaddr->sin6_addr, live_addr, INET6_ADDRSTRLEN); - asprintf(error, "sctp_recvmsg from.sin6_addr. expected: %s actual %s", + asprintf(error, "sockaddr_in6 from.sin6_addr. expected: %s actual %s", expected_addr, live_addr); return STATUS_ERR; } } break; } + } + return STATUS_OK; +} + + +static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscall, + struct expression_list *args, + char **error) +{ +#if defined(__FreeBSD__) || defined(__Linux__) + int script_fd, live_fd, live_msg_flags, result; + void *msg; + u32 len; + struct sockaddr live_from; + socklen_t live_fromlen; + struct sctp_sndrcvinfo live_sinfo; + struct expression *len_expr, *script_sinfo_expr, *script_msg_flags_expr; + struct expression *script_fromlen_expr, *script_from_expr; + + if (check_arg_count(args, 7, 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; + + msg = calloc(len, 1); + assert(msg != NULL); + begin_syscall(state, syscall); + result = sctp_recvmsg(live_fd, msg, len, (struct sockaddr*) &live_from, + &live_fromlen, &live_sinfo, &live_msg_flags); + free(msg); + + if (end_syscall(state, syscall, CHECK_EXACT, result, error)) { + return STATUS_ERR; } + script_from_expr = get_arg(args, 3, error); + if (check_sockaddr(script_from_expr, &live_from, error)) + return STATUS_ERR; + script_fromlen_expr = get_arg(args, 4, error); if (script_fromlen_expr->type != EXPR_ELLIPSIS) { int script_fromlen; @@ -3498,6 +3505,314 @@ static int syscall_sctp_sendv(struct state *state, struct syscall_spec *syscall, #endif } +#ifdef SCTP_RECVV_RCVINFO +static int check_sctp_rcvinfo(struct sctp_rcvinfo_expr *expr, + struct sctp_rcvinfo *sctp_rcvinfo, + char **error) +{ + if (expr->rcv_sid->type != EXPR_ELLIPSIS) { + u16 rcv_sid; + + if (get_u16(expr->rcv_sid, &rcv_sid, error)) { + return STATUS_ERR; + } + if (sctp_rcvinfo->rcv_sid != rcv_sid) { + asprintf(error, "sctp_rcvinfo.rcv_sid: expected: %hu actual: %hu", + rcv_sid, sctp_rcvinfo->rcv_sid); + return STATUS_ERR; + } + } + if (expr->rcv_ssn->type != EXPR_ELLIPSIS) { + u16 rcv_ssn; + + if (get_u16(expr->rcv_ssn, &rcv_ssn, error)) { + return STATUS_ERR; + } + if (sctp_rcvinfo->rcv_ssn != rcv_ssn) { + asprintf(error, "sctp_rcvinfo.rcv_ssn: expected: %hu actual: %hu", + rcv_ssn, sctp_rcvinfo->rcv_ssn); + return STATUS_ERR; + } + } + if (expr->rcv_flags->type != EXPR_ELLIPSIS) { + u16 rcv_flags; + + if (get_u16(expr->rcv_flags, &rcv_flags, error)) { + return STATUS_ERR; + } + if (sctp_rcvinfo->rcv_flags != rcv_flags) { + asprintf(error, "sctp_rcvinfo.rcv_flags: expected: %hu actual: %hu", + rcv_flags, sctp_rcvinfo->rcv_flags); + return STATUS_ERR; + } + } + if (expr->rcv_ppid->type != EXPR_ELLIPSIS) { + u32 rcv_ppid; + + if (get_u32(expr->rcv_ppid, &rcv_ppid, error)) { + return STATUS_ERR; + } + if (sctp_rcvinfo->rcv_ppid != rcv_ppid) { + asprintf(error, "sctp_rcvinfo.rcv_ppid: expected: %u actual: %u", + rcv_ppid, sctp_rcvinfo->rcv_ppid); + return STATUS_ERR; + } + } + if (expr->rcv_tsn->type != EXPR_ELLIPSIS) { + u32 rcv_tsn; + + if (get_u32(expr->rcv_tsn, &rcv_tsn, error)) { + return STATUS_ERR; + } + if (sctp_rcvinfo->rcv_tsn != rcv_tsn) { + asprintf(error, "sctp_rcvinfo.rcv_tsn: expected: %u actual: %u", + rcv_tsn, sctp_rcvinfo->rcv_tsn); + return STATUS_ERR; + } + } + if (expr->rcv_cumtsn->type != EXPR_ELLIPSIS) { + u32 rcv_cumtsn; + + if (get_u32(expr->rcv_cumtsn, &rcv_cumtsn, error)) { + return STATUS_ERR; + } + if (sctp_rcvinfo->rcv_cumtsn != rcv_cumtsn) { + asprintf(error, "sctp_rcvinfo.rcv_cumtsn: expected: %u actual: %u", + rcv_cumtsn, sctp_rcvinfo->rcv_cumtsn); + return STATUS_ERR; + } + } + if (expr->rcv_context->type != EXPR_ELLIPSIS) { + u32 rcv_context; + + if (get_u32(expr->rcv_context, &rcv_context, error)) { + return STATUS_ERR; + } + if (sctp_rcvinfo->rcv_context != rcv_context) { + asprintf(error, "sctp_rcvinfo.rcv_context: expected: %u actual: %u", + rcv_context, sctp_rcvinfo->rcv_context); + return STATUS_ERR; + } + } + return STATUS_OK; +} +#endif + +#ifdef SCTP_RECVV_NXTINFO +static int check_sctp_nxtinfo(struct sctp_nxtinfo_expr *expr, + struct sctp_nxtinfo *sctp_nxtinfo, + char **error) +{ + if (expr->nxt_sid->type != EXPR_ELLIPSIS) { + u16 nxt_sid; + + if (get_u16(expr->nxt_sid, &nxt_sid, error)) { + return STATUS_ERR; + } + if (sctp_nxtinfo->nxt_sid != nxt_sid) { + asprintf(error, "sctp_nxtinfo.nxt_sid: expected: %hu actual: %hu", + nxt_sid, sctp_nxtinfo->nxt_sid); + return STATUS_ERR; + } + } + if (expr->nxt_flags->type != EXPR_ELLIPSIS) { + u16 nxt_flags; + + if (get_u16(expr->nxt_flags, &nxt_flags, error)) { + return STATUS_ERR; + } + if (sctp_nxtinfo->nxt_flags != nxt_flags) { + asprintf(error, "sctp_nxtinfo.nxt_flags: expected: %hu actual: %hu", + nxt_flags, sctp_nxtinfo->nxt_flags); + return STATUS_ERR; + } + } + if (expr->nxt_ppid->type != EXPR_ELLIPSIS) { + u32 nxt_ppid; + + if (get_u32(expr->nxt_ppid, &nxt_ppid, error)) { + return STATUS_ERR; + } + if (sctp_nxtinfo->nxt_ppid != nxt_ppid) { + asprintf(error, "sctp_nxtinfo.nxt_ppid: expected: %u actual: %u", + nxt_ppid, sctp_nxtinfo->nxt_ppid); + return STATUS_ERR; + } + } + if (expr->nxt_length->type != EXPR_ELLIPSIS) { + u32 nxt_length; + + if (get_u32(expr->nxt_length, &nxt_length, error)) { + return STATUS_ERR; + } + if (sctp_nxtinfo->nxt_length != nxt_length) { + asprintf(error, "sctp_nxtinfo.nxt_length: expected: %u actual: %u", + nxt_length, sctp_nxtinfo->nxt_length); + return STATUS_ERR; + } + } + return STATUS_OK; +} +#endif + +#ifdef SCTP_RECVV_RN +static int check_sctp_recvv_rn(struct sctp_recvv_rn_expr *expr, + struct sctp_recvv_rn *sctp_recvv_rn, + char **error) +{ + if (expr->recvv_rcvinfo->type != EXPR_ELLIPSIS) { + if (check_sctp_rcvinfo((struct sctp_rcvinfo_expr *)expr->recvv_rcvinfo, + &sctp_recvv_rn->recvv_rcvinfo, error)) + return STATUS_ERR; + if (check_sctp_nxtinfo((struct sctp_nxtinfo_expr *)expr->recvv_nxtinfo, + &sctp_recvv_rn->recvv_nxtinfo, error)) + return STATUS_ERR; + } + return STATUS_OK; +} +#endif + +static int syscall_sctp_recvv(struct state *state, struct syscall_spec *syscall, + struct expression_list *args, + char **error) +{ +#if defined(__FreeBSD__) + int flags, iovlen, script_fd, live_fd, result_val, result = STATUS_OK; + size_t script_iovec_list_len = 0; + unsigned int infotype = 0; + socklen_t infolen, fromlen; + void *info; + struct iovec *iov; + struct sockaddr *from = NULL; + begin_syscall(state, syscall); + struct expression *iovec_expr_list, *iovcnt_expr, *addr_expr, *fromlen_expr; + struct expression *infolen_expr, *info_expr, *infotype_expr, *flags_expr; + struct sctp_recvv_rn recvv_rn; + struct sctp_rcvinfo rcvinfo; + struct sctp_nxtinfo nxtinfo; + + if (check_arg_count(args, 9, 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; + iovec_expr_list = get_arg(args, 1, error); + iovec_new(iovec_expr_list, &iov, &script_iovec_list_len, error); + iovcnt_expr = get_arg(args, 2, error); + if (get_s32(iovcnt_expr, &iovlen, error)) + return STATUS_ERR; + fromlen_expr = get_arg(args, 4, error); + if (get_u32(fromlen_expr, &fromlen, error)) + return STATUS_ERR; + + info_expr = get_arg(args, 5, error); + if (info_expr->type == EXPR_NULL) { + info = NULL; + } else if (info_expr->type == EXPR_SCTP_RCVINFO) { + info = &rcvinfo; + } else if (info_expr->type == EXPR_SCTP_NXTINFO) { + info = &nxtinfo; + } else if (info_expr->type == EXPR_SCTP_RECVV_RN) { + info = &recvv_rn; + } else { + return STATUS_ERR; + } + infolen_expr = get_arg(args, 6, error); + if (get_u32(infolen_expr, &infolen, error)) + return STATUS_ERR; + infotype = 0; + flags = 0; + addr_expr = get_arg(args, 3, error); + if (addr_expr->type == EXPR_NULL) { + from = NULL; + } else { + from = malloc(fromlen); + } + printf("fd=%d, iovlen=%d, fromlen=%d, infolen=%d, infotype=%d, flags=%d\n",live_fd, iovlen, fromlen, infolen, infotype, flags); + + begin_syscall(state, syscall); + + result_val = sctp_recvv(live_fd, iov, iovlen, (struct sockaddr *)from, &fromlen, info, &infolen, &infotype, &flags); + + iovec_free(iov, script_iovec_list_len); + + if (end_syscall(state, syscall, CHECK_EXACT, result_val, error)) { + free(from); + return STATUS_ERR; + } + if (from != NULL) { + if (check_sockaddr(addr_expr, from, error)) { + free(from); + return STATUS_ERR; + } + } + free(from); + infotype_expr = get_arg(args, 7, error); + if (infotype_expr->type != EXPR_ELLIPSIS) { + s32 script_infotype; + + if (get_s32(infotype_expr, &script_infotype, error)) { + return STATUS_ERR; + } + if (infotype != script_infotype) { + asprintf(error, "sctp_recvv infotype: expected: %u actual: %u", + script_infotype, infotype); + return STATUS_ERR; + } + } +//check info + switch(infotype){ + case SCTP_RECVV_NOINFO: + if (infolen != 0){ + asprintf(error, "infolen returned bad size for null. expected 0, actual %u", infolen); + return STATUS_ERR; + } + break; + case SCTP_RECVV_RCVINFO: + if (infolen != sizeof(struct sctp_rcvinfo)){ + asprintf(error, "infolen returned bad size for sctp_rcvinfo. expected %u, actual %u", + sizeof(struct sctp_rcvinfo), infolen); + return STATUS_ERR; + } + result = check_sctp_rcvinfo(info_expr->value.sctp_rcvinfo, info, error); + break; + case SCTP_RECVV_NXTINFO: + if (infolen != sizeof(struct sctp_nxtinfo)){ + asprintf(error, "infolen returned bad size for sctp_nxtinfo. expected %u, actual %u", + sizeof(struct sctp_nxtinfo), infolen); + return STATUS_ERR; + } + result = check_sctp_nxtinfo(info_expr->value.sctp_nxtinfo, info, error); + break; + case SCTP_RECVV_RN: + if (infolen != sizeof(struct sctp_recvv_rn)){ + asprintf(error, "infolen returned bad size for sctp_recvv_rn. expected %u, actual %u", + sizeof(struct sctp_recvv_rn), infolen); + return STATUS_ERR; + } + result = check_sctp_recvv_rn(info_expr->value.sctp_recvv_rn, info, error); + break; + default: + result = STATUS_ERR; + break; + } + flags_expr = get_arg(args, 8, error); + if (flags_expr->type != EXPR_ELLIPSIS) { + s32 script_flags; + if (get_s32(flags_expr, &script_flags, error)) { + asprintf(error, "sctp_recvv flags bad return value. expected %d, actual %d", + script_flags, flags); + return STATUS_ERR; + } + } + return result; +#else + asprintf(error, "sctp_recvv is not supported"); + return STATUS_ERR; +#endif +} + /* A dispatch table with all the system calls that we support... */ struct system_call_entry { const char *name; @@ -3532,6 +3847,7 @@ struct system_call_entry system_call_table[] = { {"sctp_sendmsg", syscall_sctp_sendmsg}, {"sctp_recvmsg", syscall_sctp_recvmsg}, {"sctp_sendv", syscall_sctp_sendv}, + {"sctp_recvv", syscall_sctp_recvv} }; /* Evaluate the system call arguments and invoke the system call. */ diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index c5b493ea7814ee168f8cbd7b47c32d1295c44864..21d3a1c9cc11974cca260a261ae28a7d0d640ef3 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -82,6 +82,9 @@ struct expression_type_entry expression_type_table[] = { { EXPR_SCTP_PRINFO, "sctp_prinfo" }, { EXPR_SCTP_AUTHINFO, "sctp_authinfo" }, { EXPR_SCTP_SENDV_SPA, "sctp_sendv_spa" }, + { EXPR_SCTP_RCVINFO, "sctp_rcvinfo" }, + { EXPR_SCTP_NXTINFO, "sctp_nxtinfo" }, + { EXPR_SCTP_RECVV_RN, "sctp_recvv_rn " }, { NUM_EXPR_TYPES, NULL} }; @@ -394,6 +397,25 @@ void free_expression(struct expression *expression) free_expression(expression->value.sctp_sendv_spa->sendv_prinfo); free_expression(expression->value.sctp_sendv_spa->sendv_authinfo); break; + case EXPR_SCTP_RCVINFO: + free_expression(expression->value.sctp_rcvinfo->rcv_sid); + free_expression(expression->value.sctp_rcvinfo->rcv_ssn); + free_expression(expression->value.sctp_rcvinfo->rcv_flags); + free_expression(expression->value.sctp_rcvinfo->rcv_ppid); + free_expression(expression->value.sctp_rcvinfo->rcv_tsn); + free_expression(expression->value.sctp_rcvinfo->rcv_cumtsn); + free_expression(expression->value.sctp_rcvinfo->rcv_context); + break; + case EXPR_SCTP_NXTINFO: + free_expression(expression->value.sctp_nxtinfo->nxt_sid); + free_expression(expression->value.sctp_nxtinfo->nxt_flags); + free_expression(expression->value.sctp_nxtinfo->nxt_ppid); + free_expression(expression->value.sctp_nxtinfo->nxt_length); + break; + case EXPR_SCTP_RECVV_RN: + free_expression(expression->value.sctp_recvv_rn->recvv_rcvinfo); + free_expression(expression->value.sctp_recvv_rn->recvv_nxtinfo); + break; case EXPR_WORD: assert(expression->value.string); free(expression->value.string); @@ -1135,6 +1157,112 @@ static int evaluate_sctp_sendv_spa_expression(struct expression *in, return STATUS_OK; } +static int evaluate_sctp_rcvinfo_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_rcvinfo_expr *in_info; + struct sctp_rcvinfo_expr *out_info; + + assert(in->type == EXPR_SCTP_RCVINFO); + assert(in->value.sctp_rcvinfo); + assert(out->type == EXPR_SCTP_RCVINFO); + + out->value.sctp_rcvinfo = calloc(1, sizeof(struct sctp_rcvinfo_expr)); + + in_info = in->value.sctp_rcvinfo; + out_info = out->value.sctp_rcvinfo; + + if (evaluate(in_info->rcv_sid, + &out_info->rcv_sid, + error)) + return STATUS_ERR; + if (evaluate(in_info->rcv_ssn, + &out_info->rcv_ssn, + error)) + return STATUS_ERR; + if (evaluate(in_info->rcv_flags, + &out_info->rcv_flags, + error)) + return STATUS_ERR; + if (evaluate(in_info->rcv_ppid, + &out_info->rcv_ppid, + error)) + return STATUS_ERR; + if (evaluate(in_info->rcv_tsn, + &out_info->rcv_tsn, + error)) + return STATUS_ERR; + if (evaluate(in_info->rcv_cumtsn, + &out_info->rcv_cumtsn, + error)) + return STATUS_ERR; + if (evaluate(in_info->rcv_context, + &out_info->rcv_context, + error)) + return STATUS_ERR; + + return STATUS_OK; +} + +static int evaluate_sctp_nxtinfo_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_nxtinfo_expr *in_info; + struct sctp_nxtinfo_expr *out_info; + + assert(in->type == EXPR_SCTP_NXTINFO); + assert(in->value.sctp_nxtinfo); + assert(out->type == EXPR_SCTP_NXTINFO); + + out->value.sctp_nxtinfo = calloc(1, sizeof(struct sctp_nxtinfo_expr)); + + in_info = in->value.sctp_nxtinfo; + out_info = out->value.sctp_nxtinfo; + + if (evaluate(in_info->nxt_sid, + &out_info->nxt_sid, + error)) + return STATUS_ERR; + if (evaluate(in_info->nxt_flags, + &out_info->nxt_flags, + error)) + return STATUS_ERR; + if (evaluate(in_info->nxt_ppid, + &out_info->nxt_ppid, + error)) + return STATUS_ERR; + if (evaluate(in_info->nxt_length, + &out_info->nxt_length, + error)) + return STATUS_ERR; + return STATUS_OK; +} + +static int evaluate_sctp_recvv_rn_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_recvv_rn_expr *in_rn; + struct sctp_recvv_rn_expr *out_rn; + + assert(in->type == EXPR_SCTP_RECVV_RN); + assert(in->value.sctp_recvv_rn); + assert(out->type == EXPR_SCTP_RECVV_RN); + + out->value.sctp_recvv_rn = calloc(1, sizeof(struct sctp_recvv_rn_expr)); + + in_rn = in->value.sctp_recvv_rn; + out_rn = out->value.sctp_recvv_rn; + + if (evaluate(in_rn->recvv_rcvinfo, + &out_rn->recvv_rcvinfo, + error)) + return STATUS_ERR; + + return STATUS_OK; +} static int evaluate(struct expression *in, struct expression **out_ptr, char **error) { @@ -1208,6 +1336,15 @@ static int evaluate(struct expression *in, case EXPR_SCTP_SENDV_SPA: result = evaluate_sctp_sendv_spa_expression(in, out, error); break; + case EXPR_SCTP_RCVINFO: + result = evaluate_sctp_rcvinfo_expression(in, out, error); + break; + case EXPR_SCTP_NXTINFO: + result = evaluate_sctp_nxtinfo_expression(in, out, error); + break; + case EXPR_SCTP_RECVV_RN: + result = evaluate_sctp_recvv_rn_expression(in, out, error); + break; case EXPR_WORD: out->type = EXPR_INTEGER; if (symbol_to_int(in->value.string, diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index 35de4e878fc067eb555bca949431b4b962ba5804..c47ec124700990434b1da23d934fa328db4515e9 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -62,6 +62,9 @@ enum expression_t { EXPR_SCTP_PRINFO, /* struct sctp_prinfo for syscall sctp_sendv */ EXPR_SCTP_AUTHINFO, /* struct sctp_authinfo for syscall sctp_sendv */ EXPR_SCTP_SENDV_SPA, /* struct sctp_sendv_spa for syscall sctp_sendv */ + EXPR_SCTP_RCVINFO, /* struct sctp_rcvinfo for syscall sctp_recvv */ + EXPR_SCTP_NXTINFO, /* struct sctp_nxtinfo for syscall sctp_recvv */ + EXPR_SCTP_RECVV_RN, /* struct sctp_recvv_rn for syscall sctp_recvv */ NUM_EXPR_TYPES, }; /* Convert an expression type to a human-readable string */ @@ -97,6 +100,9 @@ struct expression { struct sctp_prinfo_expr *sctp_prinfo; struct sctp_authinfo_expr *sctp_authinfo; struct sctp_sendv_spa_expr *sctp_sendv_spa; + struct sctp_rcvinfo_expr *sctp_rcvinfo; + struct sctp_nxtinfo_expr *sctp_nxtinfo; + struct sctp_recvv_rn_expr *sctp_recvv_rn; } value; const char *format; /* the printf format for printing the value */ }; @@ -268,6 +274,31 @@ struct sctp_sendv_spa_expr { struct expression *sendv_authinfo; }; +/* Parse tree for sctp_rcvinfo in sctp_recvv syscall. */ +struct sctp_rcvinfo_expr { + struct expression *rcv_sid; + struct expression *rcv_ssn; + struct expression *rcv_flags; + struct expression *rcv_ppid; + struct expression *rcv_tsn; + struct expression *rcv_cumtsn; + struct expression *rcv_context; +}; + +/* Parse tree for sctp_nxtinfo in sctp_recvv syscall. */ +struct sctp_nxtinfo_expr { + struct expression *nxt_sid; + struct expression *nxt_flags; + struct expression *nxt_ppid; + struct expression *nxt_length; +}; + +/* Parse tree for sctp_recvv_rn in sctp_recvv syscall. */ +struct sctp_recvv_rn_expr { + struct expression *recvv_rcvinfo; + struct expression *recvv_nxtinfo; +}; + /* The errno-related info from strace to summarize a system call error */ struct errno_spec { const char *errno_macro; /* errno symbol (C macro name) */ diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c index e6e4d75ccfd85fe193e9c7ee836e7a17469f0250..284e156cd32a93f6df81bf10e15037c7d78eb383 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -195,7 +195,12 @@ struct int_symbol platform_symbols_table[] = { { SCTP_SEND_SNDINFO_VALID, "SCTP_SEND_SNDINFO_VALID" }, { SCTP_SEND_PRINFO_VALID, "SCTP_SEND_PRINFO_VALID" }, { SCTP_SEND_AUTHINFO_VALID, "SCTP_SEND_AUTHINFO_VALID" }, - + { SCTP_RECVV_NOINFO, "SCTP_RECVV_NOINFO" }, + { SCTP_RECVV_RCVINFO, "SCTP_RECVV_RCVINFO" }, + { SCTP_RECVV_NXTINFO, "SCTP_RECVV_NXTINFO" }, + { SCTP_RECVV_RN, "SCTP_RECVV_RN" }, + { SCTP_RECVRCVINFO, "SCTP_RECVRCVINFO" }, + { SCTP_RECVNXTINFO, "SCTP_RECVNXTINFO" }, /* /usr/include/netinet/tcp.h */ { TCP_NODELAY, "TCP_NODELAY" }, { TCP_MAXSEG, "TCP_MAXSEG" },