diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 8aa42a8e1e473ce15c23d2cd1f91a8a0acb4258a..08ff374e467d804e688f4187bf05bab67d588d58 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -164,7 +164,12 @@ sin_port return SIN_PORT; sin_addr return SIN_ADDR; msg_name return MSG_NAME; msg_iov return MSG_IOV; +msg_control return MSG_CONTROL; msg_flags return MSG_FLAGS; +cmsg_len return CMSG_LEN; +cmsg_level return CMSG_LEVEL; +cmsg_type return CMSG_TYPE; +cmsg_data return CMSG_DATA; fd return FD; events return EVENTS; revents return REVENTS; @@ -259,6 +264,7 @@ snd_sid return SND_SID; snd_flags return SND_FLAGS; snd_ppid return SND_PPID; snd_context return SND_CONTEXT; +snd_assoc_id return SND_ASSOC_ID; ssb_adaptation_ind return SSB_ADAPTATION_IND; sinfo_stream return SINFO_STREAM; sinfo_ssn return SINFO_SSN; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index 42e6c1928c59dd4c4406a80d1e19f8d9a1957805..357bdc61125699e80bb7017f59f3e0bfc5fb2faa 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -494,7 +494,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, */ %token ELLIPSIS %token <reserved> SA_FAMILY SIN_PORT SIN_ADDR _HTONS_ _HTONL_ INET_ADDR -%token <reserved> MSG_NAME MSG_IOV MSG_FLAGS +%token <reserved> MSG_NAME MSG_IOV MSG_FLAGS MSG_CONTROL CMSG_LEN CMSG_LEVEL CMSG_TYPE CMSG_DATA %token <reserved> FD EVENTS REVENTS ONOFF LINGER %token <reserved> ACK ECR EOL MSS NOP SACK SACKOK TIMESTAMP VAL WIN WSCALE PRO %token <reserved> FAST_OPEN @@ -538,7 +538,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> SPP_FLAGS SPP_IPV6_FLOWLABEL_ SPP_DSCP_ %token <reserved> SASOC_ASOCMAXRXT SASOC_NUMBER_PEER_DESTINATIONS SASOC_PEER_RWND %token <reserved> SASOC_LOCAL_RWND SASOC_COOKIE_LIFE SE_TYPE SE_ON -%token <reserved> SND_SID SND_FLAGS SND_PPID SND_CONTEXT SSB_ADAPTATION_IND +%token <reserved> SND_SID SND_FLAGS SND_PPID SND_CONTEXT SND_ASSOC_ID SSB_ADAPTATION_IND %token <reserved> BAD_CRC32C NULL_ %token <reserved> SINFO_STREAM SINFO_SSN SINFO_FLAGS SINFO_PPID SINFO_CONTEXT %token <reserved> SINFO_TIMETOLIVE SINFO_TSN SINFO_CUMTSN @@ -598,7 +598,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression_list> expression_list function_arguments %type <expression> expression binary_expression array %type <expression> decimal_integer hex_integer data -%type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents +%type <expression> inaddr sockaddr msghdr cmsghdr cmsg_level cmsg_type cmsg_data +%type <expression> iovec pollfd opt_revents %type <expression> linger l_onoff l_linger %type <expression> sctp_status sstat_state sstat_rwnd sstat_unackdata sstat_penddata %type <expression> sstat_instrms sstat_outstrms sstat_fragmentation_point sstat_primary @@ -611,7 +612,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> spinfo_address spinfo_state spinfo_cwnd spinfo_srtt spinfo_rto spinfo_mtu %type <expression> sasoc_asocmaxrxt sasoc_number_peer_destinations sasoc_peer_rwnd %type <expression> sasoc_local_rwnd sasoc_cookie_life sctp_assocparams -%type <expression> sctp_sndinfo snd_sid snd_flags snd_ppid snd_context +%type <expression> sctp_sndinfo snd_sid snd_flags snd_ppid snd_assoc_id snd_context %type <expression> sctp_event se_type se_on sctp_setadaptation null %type <expression> sctp_sndrcvinfo sinfo_stream sinfo_ssn sinfo_flags sinfo_ppid sinfo_context %type <expression> sinfo_timetolive sinfo_tsn sinfo_cumtsn @@ -2458,6 +2459,9 @@ expression | msghdr { $$ = $1; } +| cmsghdr { + $$ = $1; +} | iovec { $$ = $1; } @@ -2630,6 +2634,7 @@ data msghdr : '{' MSG_NAME '(' ELLIPSIS ')' '=' ELLIPSIS ',' MSG_IOV '(' decimal_integer ')' '=' array ',' + MSG_CONTROL '('decimal_integer ')' '=' array ',' MSG_FLAGS '=' expression '}' { struct msghdr_expr *msg_expr = calloc(1, sizeof(struct msghdr_expr)); $$ = new_expression(EXPR_MSGHDR); @@ -2638,11 +2643,60 @@ msghdr msg_expr->msg_namelen = new_expression(EXPR_ELLIPSIS); msg_expr->msg_iov = $14; msg_expr->msg_iovlen = $11; - msg_expr->msg_flags = $18; - /* TODO(ncardwell): msg_control, msg_controllen */ + msg_expr->msg_controllen= $18; + msg_expr->msg_control = $21; + msg_expr->msg_flags = $25; +} +; + +cmsg_level +: CMSG_LEVEL '=' INTEGER { + if (!is_valid_s32($3)) { + semantic_error("cmsg_level out of range"); + } + $$ = new_integer_expression($3, "%d"); +} +| CMSG_LEVEL '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; } +| CMSG_LEVEL '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } ; +cmsg_type +: CMSG_TYPE '=' INTEGER { + if (!is_valid_s32($3)) { + semantic_error("cmsg_level out of range"); + } + $$ = new_integer_expression($3, "%d"); +} +| CMSG_TYPE '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| CMSG_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +cmsg_data +: CMSG_DATA '=' sctp_sndinfo { $$ = $3; } +| CMSG_DATA '=' sctp_prinfo { $$ = $3; } +| CMSG_DATA '=' sctp_authinfo { $$ = $3; } +| CMSG_DATA '=' sockaddr { $$ = $3; } +; + +cmsghdr +: '{' CMSG_LEN '=' INTEGER ',' cmsg_level ',' cmsg_type ',' cmsg_data '}' { + $$ = new_expression(EXPR_CMSGHDR); + $$->value.cmsghdr = calloc(1, sizeof(struct cmsghdr_expr)); + if (!is_valid_s32($4)) { + semantic_error("cmsg_len out of range"); + } + $$->value.cmsghdr->cmsg_len = new_integer_expression($4, "%u"); + $$->value.cmsghdr->cmsg_level = $6; + $$->value.cmsghdr->cmsg_type = $8; + $$->value.cmsghdr->cmsg_data = $10; +}; + iovec : '{' data ',' decimal_integer '}' { struct iovec_expr *iov_expr = calloc(1, sizeof(struct iovec_expr)); @@ -3260,14 +3314,30 @@ snd_context | SND_CONTEXT '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } ; +snd_assoc_id +: SND_ASSOC_ID '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("snd_assoc_id out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SND_ASSOC_ID '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| SND_ASSOC_ID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + + sctp_sndinfo -: '{' snd_sid ',' snd_flags ',' snd_ppid ',' snd_context '}' { +: '{' snd_sid ',' snd_flags ',' snd_ppid ',' snd_context ',' snd_assoc_id'}' { $$ = new_expression(EXPR_SCTP_SNDINFO); $$->value.sctp_sndinfo = calloc(1, sizeof(struct sctp_sndinfo_expr)); $$->value.sctp_sndinfo->snd_sid = $2; $$->value.sctp_sndinfo->snd_flags = $4; $$->value.sctp_sndinfo->snd_ppid = $6; $$->value.sctp_sndinfo->snd_context = $8; + $$->value.sctp_sndinfo->snd_assoc_id = $10; } ; diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index c54a41b58000e0059c0ac12304c4d3a2d1a19a40..97b006664e42efe40a93ee7efdac7fed0fc03138 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -52,7 +52,14 @@ static int to_live_fd(struct state *state, int script_fd, int *live_fd, static int check_sctp_notification(struct iovec *iov, struct expression *iovec_expr, char **error); #endif - +#if defined(__FreeBSD__) +static int parse_expression_to_sctp_sndinfo(struct expression *expr, struct sctp_sndinfo *info, + char **error); +static int parse_expression_to_sctp_prinfo(struct expression *expr, struct sctp_prinfo *info, + char **error); +static int parse_expression_to_sctp_authinfo(struct expression *expr, struct sctp_authinfo *info, + char **error); +#endif /* Provide a wrapper for the Linux gettid() system call (glibc does not). */ static pid_t gettid(void) @@ -413,6 +420,69 @@ static int get_sockstorage_arg(struct expression *arg, struct sockaddr_storage * } #endif +static int check_sockaddr(struct expression *sockaddr_expr, struct sockaddr *live_addr, char **error) { + + if (sockaddr_expr->type != EXPR_ELLIPSIS) { + struct sockaddr *script_addr; + 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, "Bad type for sockaddr"); + return STATUS_ERR; + } + 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_addr; + if (live_sockaddr->sin_port != script_sockaddr->sin_port) { + asprintf(error, "sockaddr_in from.sinport. expected: %d actual %d", + ntohs(script_sockaddr->sin_port), ntohs(live_sockaddr->sin_port)); + return STATUS_ERR; + } + if (live_sockaddr->sin_addr.s_addr != script_sockaddr->sin_addr.s_addr) { + 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, "sockaddr_in from.sin_addr. expected: %s actual %s", + expected_addr, inet_ntoa(live_sockaddr->sin_addr)); + free(expected_addr); + return STATUS_ERR; + } + } + break; + case AF_INET6: + { + struct sockaddr_in6 *script_sockaddr = (struct sockaddr_in6*)script_addr; + struct sockaddr_in6 *live_sockaddr = (struct sockaddr_in6*)live_addr; + if (live_sockaddr->sin6_port != script_sockaddr->sin6_port) { + asprintf(error, "sockaddr_in6 from.sinport. expected: %d actual %d", + ntohs(script_sockaddr->sin6_port), ntohs(live_sockaddr->sin6_port)); + return STATUS_ERR; + } + if (live_sockaddr->sin6_addr.s6_addr != script_sockaddr->sin6_addr.s6_addr) { + char expected_addr[INET6_ADDRSTRLEN]; + 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, "sockaddr_in6 from.sin6_addr. expected: %s actual %s", + expected_addr, live_addr); + return STATUS_ERR; + } + } + break; + } + } + return STATUS_OK; +} + #if defined(__FreeBSD__) || defined(linux) int check_u8_expr(struct expression *expr, u8 value, char *val_name, char **error) { if (expr->type != EXPR_ELLIPSIS) { @@ -463,7 +533,7 @@ int check_s32_expr(struct expression *expr, s16 value, char *val_name, char **er } #if defined(__FreeBSD__) || defined(linux) -int check_u32_expr(struct expression *expr, u16 value, char *val_name, char **error) { +int check_u32_expr(struct expression *expr, u32 value, char *val_name, char **error) { if (expr->type != EXPR_ELLIPSIS) { u32 script_val; @@ -594,6 +664,123 @@ error_out: return status; } +/* Allocate and fill in an +cmsghdr described by the given expression. + * Return STATUS_OK if the expression is a valid cmsghdr. Otherwise + * fill in the error with a human-readable error message and return + * STATUS_ERR. + */ +static int cmsg_new(struct expression *expression, + void **cmsg_ptr, size_t *cmsg_len_ptr, char **error) +{ + struct expression_list *list; + int list_len = 0, i = 0; + size_t cmsg_size = 0; + struct cmsghdr *cmsg; + + if (check_type(expression, EXPR_LIST, error)) + return STATUS_ERR; + list = expression->value.list; + list_len = expression_list_length(list); + //calc size of cmsg in list + if (list_len == 0){ + cmsg_ptr = NULL; + return STATUS_OK; + } + for (i = 0; i < list_len; i++) { + struct expression *cmsg_expr; + cmsg_expr = get_arg(list, i, error); + switch (cmsg_expr->value.cmsghdr->cmsg_data->type) { + case EXPR_SCTP_SNDINFO: + cmsg_size += CMSG_SPACE(sizeof(struct sctp_sndinfo)); + break; + case EXPR_SCTP_PRINFO: + cmsg_size += CMSG_SPACE(sizeof(struct sctp_prinfo)); + break; + case EXPR_SCTP_AUTHINFO: + cmsg_size += CMSG_SPACE(sizeof(struct sctp_authinfo)); + break; + case EXPR_SOCKET_ADDRESS_IPV4: + cmsg_size += CMSG_SPACE(sizeof(struct in_addr)); + break; + case EXPR_SOCKET_ADDRESS_IPV6: + cmsg_size += CMSG_SPACE(sizeof(struct in6_addr)); + break; + default: + asprintf(error,"cmsg %d type not valid", i); + return STATUS_ERR; + } + } + + *cmsg_len_ptr = cmsg_size; + cmsg = calloc(1, cmsg_size); + *cmsg_ptr = (void *)cmsg; + + for (i = 0; i < list_len; i++) { + struct expression *expr; + struct cmsghdr_expr *cmsg_expr; + + expr = get_arg(list, i, error); + if(check_type(expr, EXPR_CMSGHDR, error)) + goto error_out; + cmsg_expr = expr->value.cmsghdr; + if (get_u32(cmsg_expr->cmsg_len, &cmsg->cmsg_len, error)) + goto error_out; + if (get_s32(cmsg_expr->cmsg_level, &cmsg->cmsg_level, error)) + goto error_out; + if (get_s32(cmsg_expr->cmsg_type, &cmsg->cmsg_type, error)) + goto error_out; + + switch(cmsg_expr->cmsg_data->type) { + case EXPR_SCTP_SNDINFO: { + struct sctp_sndinfo info; + if (parse_expression_to_sctp_sndinfo(cmsg_expr->cmsg_data, &info, error)) { + goto error_out; + } + memcpy(CMSG_DATA(cmsg), &info, sizeof(struct sctp_sndinfo)); + cmsg = (struct cmsghdr *) ((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo))); + break; + } + case EXPR_SCTP_PRINFO: { + struct sctp_prinfo info; + if (parse_expression_to_sctp_prinfo(cmsg_expr->cmsg_data, &info, error)) { + goto error_out; + } + memcpy(CMSG_DATA(cmsg), &info, sizeof(struct sctp_prinfo)); + cmsg = (struct cmsghdr *) ((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo))); + break; + } + case EXPR_SCTP_AUTHINFO: { + struct sctp_authinfo info; + if (parse_expression_to_sctp_authinfo(cmsg_expr->cmsg_data, &info, error)) { + goto error_out; + } + memcpy(CMSG_DATA(cmsg), &info, sizeof(struct sctp_authinfo)); + cmsg = (struct cmsghdr *) ((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo))); + break; + } + case EXPR_SOCKET_ADDRESS_IPV4: + memcpy(CMSG_DATA(cmsg), &cmsg_expr->cmsg_data->value.socket_address_ipv4->sin_addr, sizeof(struct in_addr)); + cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in_addr))); + break; + case EXPR_SOCKET_ADDRESS_IPV6: + memcpy(CMSG_DATA(cmsg), &cmsg_expr->cmsg_data->value.socket_address_ipv6->sin6_addr, sizeof(struct in6_addr)); + cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in6_addr))); + break; + default: + asprintf(error,"cmsg.cmsg_data %d type not valid", i); + goto error_out; + } + } + + return STATUS_OK; +error_out: + free(*cmsg_ptr); + *cmsg_ptr = NULL; + *cmsg_len_ptr = 0; + return STATUS_ERR; +} + /* Free all the space used by the given msghdr. */ static void msghdr_free(struct msghdr *msg, size_t iov_len) { @@ -615,6 +802,7 @@ static int msghdr_new(struct expression *expression, struct msghdr_expr *msg_expr; /* input expression from script */ socklen_t name_len = sizeof(struct sockaddr_storage); struct msghdr *msg = NULL; /* live output */ + size_t cmsg_len = 0; if (check_type(expression, EXPR_MSGHDR, error)) goto error_out; @@ -652,14 +840,29 @@ static int msghdr_new(struct expression *expression, goto error_out; } + if (msg_expr->msg_control != NULL) { + if (cmsg_new(msg_expr->msg_control, &msg->msg_control, &cmsg_len, error)) + goto error_out; + } + + if (msg_expr->msg_controllen != NULL) { + if (get_u32(msg_expr->msg_controllen, &msg->msg_controllen, error)) + goto error_out; + } + + if (msg->msg_controllen != cmsg_len) { + asprintf(error, + "msg_controllen %u does not match %u size of cmsghdr array", + msg->msg_controllen, cmsg_len); + goto error_out; + } + if (msg_expr->msg_flags != NULL) { if (get_s32(msg_expr->msg_flags, &s32_val, error)) goto error_out; msg->msg_flags = s32_val; } - /* TODO(ncardwell): msg_control, msg_controllen */ - status = STATUS_OK; error_out: @@ -1707,7 +1910,7 @@ static int syscall_sendmsg(struct state *state, struct syscall_spec *syscall, } begin_syscall(state, syscall); - + result = sendmsg(live_fd, msg, flags); status = end_syscall(state, syscall, CHECK_EXACT, result, error); @@ -2162,6 +2365,9 @@ static int check_sctp_sndinfo(struct sctp_sndinfo_expr *expr, if (check_u32_expr(expr->snd_context, sctp_sndinfo->snd_context, "sctp_sndinfo.snd_context", error)) return STATUS_ERR; + if (check_u32_expr(expr->snd_assoc_id, sctp_sndinfo->snd_assoc_id, + "sctp_sndinfo.snd_assoc_id", error)) + return STATUS_ERR; return STATUS_OK; } @@ -2323,7 +2529,12 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, case EXPR_SCTP_SNDINFO: live_optval = malloc(sizeof(struct sctp_sndinfo)); live_optlen = sizeof(struct sctp_sndinfo); - ((struct sctp_sndinfo *)live_optval)->snd_assoc_id = 0; + if (get_u32(val_expression->value.sctp_sndinfo->snd_assoc_id, + &((struct sctp_sndinfo *)live_optval)->snd_assoc_id, + error)) { + free(live_optval); + return STATUS_ERR; + } break; #endif #ifdef SCTP_ADAPTATION_LAYER @@ -2707,7 +2918,6 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, #endif #ifdef SCTP_DEFAULT_SNDINFO case EXPR_SCTP_SNDINFO: - sndinfo.snd_assoc_id = 0; if (get_u16(val_expression->value.sctp_sndinfo->snd_sid, &sndinfo.snd_sid, error)) { return STATUS_ERR; @@ -2724,6 +2934,10 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, &sndinfo.snd_context, error)) { return STATUS_ERR; } + if (get_u32(val_expression->value.sctp_sndinfo->snd_assoc_id, + &sndinfo.snd_assoc_id, error)) { + return STATUS_ERR; + } optval = &sndinfo; break; #endif @@ -2974,68 +3188,6 @@ static int check_sctp_sndrcvinfo(struct sctp_sndrcvinfo_expr *expr, return STATUS_OK; } -static int check_sockaddr(struct expression *sockaddr_expr, struct sockaddr *live_addr, char **error) { - - if (sockaddr_expr->type != EXPR_ELLIPSIS) { - struct sockaddr *script_addr; - 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, "Bad type for sockaddr"); - return STATUS_ERR; - } - 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_addr; - if (live_sockaddr->sin_port != script_sockaddr->sin_port) { - asprintf(error, "sockaddr_in from.sinport. expected: %d actual %d", - ntohs(script_sockaddr->sin_port), ntohs(live_sockaddr->sin_port)); - return STATUS_ERR; - } - if (live_sockaddr->sin_addr.s_addr != script_sockaddr->sin_addr.s_addr) { - 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, "sockaddr_in from.sin_addr. expected: %s actual %s", - expected_addr, inet_ntoa(live_sockaddr->sin_addr)); - free(expected_addr); - return STATUS_ERR; - } - } - break; - case AF_INET6: - { - struct sockaddr_in6 *script_sockaddr = (struct sockaddr_in6*)script_addr; - struct sockaddr_in6 *live_sockaddr = (struct sockaddr_in6*)live_addr; - if (live_sockaddr->sin6_port != script_sockaddr->sin6_port) { - asprintf(error, "sockaddr_in6 from.sinport. expected: %d actual %d", - ntohs(script_sockaddr->sin6_port), ntohs(live_sockaddr->sin6_port)); - return STATUS_ERR; - } - if (live_sockaddr->sin6_addr.s6_addr != script_sockaddr->sin6_addr.s6_addr) { - char expected_addr[INET6_ADDRSTRLEN]; - 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, "sockaddr_in6 from.sin6_addr. expected: %s actual %s", - expected_addr, live_addr); - return STATUS_ERR; - } - } - break; - } - } - return STATUS_OK; -} #endif static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscall, @@ -3120,7 +3272,6 @@ static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscal static int parse_expression_to_sctp_sndinfo(struct expression *expr, struct sctp_sndinfo *info, char **error) { if (expr->type == EXPR_SCTP_SNDINFO) { struct sctp_sndinfo_expr *sndinfo_expr = expr->value.sctp_sndinfo; - info->snd_assoc_id = 0; if (get_u16(sndinfo_expr->snd_sid, &info->snd_sid, error)) { return STATUS_ERR; } @@ -3133,6 +3284,9 @@ static int parse_expression_to_sctp_sndinfo(struct expression *expr, struct sctp if (get_u32(sndinfo_expr->snd_context, &info->snd_context, error)) { return STATUS_ERR; } + if (get_u32(sndinfo_expr->snd_assoc_id, &info->snd_assoc_id, error)) { + return STATUS_ERR; + } } else { return STATUS_ERR; } @@ -3785,7 +3939,6 @@ static int check_sctp_notification(struct iovec *iov, return STATUS_ERR; break; case EXPR_ELLIPSIS: - printf("check Ellipsis\n"); break; default: asprintf(error, "Bad type for iov_base. Can't check type %s", diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 336374356ad389bd00034b6d481c417767d348d8..58604198be75911c62d284e264349820ee1ca0da 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -65,6 +65,7 @@ struct expression_type_entry expression_type_table[] = { { EXPR_LIST, "list" }, { EXPR_IOVEC, "iovec" }, { EXPR_MSGHDR, "msghdr" }, + { EXPR_CMSGHDR, "cmsghdr"}, { EXPR_POLLFD, "pollfd" }, { EXPR_SCTP_RTOINFO, "sctp_rtoinfo"}, { EXPR_SCTP_INITMSG, "sctp_initmsg"}, @@ -394,6 +395,7 @@ void free_expression(struct expression *expression) free_expression(expression->value.sctp_sndinfo->snd_flags); free_expression(expression->value.sctp_sndinfo->snd_ppid); free_expression(expression->value.sctp_sndinfo->snd_context); + free_expression(expression->value.sctp_sndinfo->snd_assoc_id); break; case EXPR_SCTP_SETADAPTATION: free_expression(expression->value.sctp_setadaptation->ssb_adaptation_ind); @@ -563,8 +565,16 @@ void free_expression(struct expression *expression) free_expression(expression->value.msghdr->msg_namelen); free_expression(expression->value.msghdr->msg_iov); free_expression(expression->value.msghdr->msg_iovlen); + free_expression(expression->value.msghdr->msg_control); + free_expression(expression->value.msghdr->msg_controllen); free_expression(expression->value.msghdr->msg_flags); break; + case EXPR_CMSGHDR: + free_expression(expression->value.cmsghdr->cmsg_len); + free_expression(expression->value.cmsghdr->cmsg_level); + free_expression(expression->value.cmsghdr->cmsg_type); + free_expression(expression->value.cmsghdr->cmsg_data); + break; case EXPR_POLLFD: assert(expression->value.pollfd); free_expression(expression->value.pollfd->fd); @@ -656,6 +666,33 @@ static int evaluate_iovec_expression(struct expression *in, return STATUS_OK; } +static int evaluate_cmsghdr_expression(struct expression *in, + struct expression *out, char **error) +{ + struct cmsghdr_expr *in_cmsg; + struct cmsghdr_expr *out_cmsg; + + assert(in->type == EXPR_CMSGHDR); + assert(in->value.msghdr); + assert(out->type == EXPR_CMSGHDR); + + out->value.cmsghdr = calloc(1, sizeof(struct cmsghdr_expr)); + + in_cmsg = in->value.cmsghdr; + out_cmsg = out->value.cmsghdr; + + if (evaluate(in_cmsg->cmsg_len, &out_cmsg->cmsg_len, error)) + return STATUS_ERR; + if (evaluate(in_cmsg->cmsg_level, &out_cmsg->cmsg_level, error)) + return STATUS_ERR; + if (evaluate(in_cmsg->cmsg_type, &out_cmsg->cmsg_type, error)) + return STATUS_ERR; + if (evaluate(in_cmsg->cmsg_data, &out_cmsg->cmsg_data, error)) + return STATUS_ERR; + + return STATUS_OK; +} + static int evaluate_msghdr_expression(struct expression *in, struct expression *out, char **error) { @@ -679,6 +716,10 @@ static int evaluate_msghdr_expression(struct expression *in, return STATUS_ERR; if (evaluate(in_msg->msg_iovlen, &out_msg->msg_iovlen, error)) return STATUS_ERR; + if (evaluate(in_msg->msg_control, &out_msg->msg_control, error)) + return STATUS_ERR; + if (evaluate(in_msg->msg_controllen, &out_msg->msg_controllen,error)) + return STATUS_ERR; if (evaluate(in_msg->msg_flags, &out_msg->msg_flags, error)) return STATUS_ERR; @@ -1159,6 +1200,10 @@ static int evaluate_sctp_sndinfo_expression(struct expression *in, &out_sndinfo->snd_context, error)) return STATUS_ERR; + if (evaluate(in_sndinfo->snd_assoc_id, + &out_sndinfo->snd_assoc_id, + error)) + return STATUS_ERR; return STATUS_OK; } @@ -2065,6 +2110,9 @@ static int evaluate(struct expression *in, case EXPR_MSGHDR: result = evaluate_msghdr_expression(in, out, error); break; + case EXPR_CMSGHDR: + result = evaluate_cmsghdr_expression(in, out, error); + break; case EXPR_POLLFD: result = evaluate_pollfd_expression(in, out, error); break; diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index bb60524ff45952a372108df958fdfbef5f63567a..5dccd49ca7b55432e1c8cf326e6f04379d471f6d 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -45,6 +45,7 @@ enum expression_t { EXPR_LIST, /* list of expressions */ EXPR_IOVEC, /* expression tree for an iovec struct */ EXPR_MSGHDR, /* expression tree for a msghdr struct */ + EXPR_CMSGHDR, /* expression tree for a cmsghdr struct */ EXPR_POLLFD, /* expression tree for a pollfd struct */ EXPR_SCTP_RTOINFO, /* struct sctp_rtoinfo for SCTP_RTOINFO */ EXPR_SCTP_INITMSG, /* struct sctp_initmsg for SCTP_INITMSG */ @@ -95,6 +96,7 @@ struct expression { struct expression_list *list; struct iovec_expr *iovec; struct msghdr_expr *msghdr; + struct cmsghdr_expr *cmsghdr; struct pollfd_expr *pollfd; struct sctp_rtoinfo_expr *sctp_rtoinfo; struct sctp_initmsg_expr *sctp_initmsg; @@ -158,9 +160,19 @@ struct msghdr_expr { struct expression *msg_namelen; struct expression *msg_iov; struct expression *msg_iovlen; + struct expression *msg_control; + struct expression *msg_controllen; struct expression *msg_flags; }; +/* Parse tree for a cmsghdr struct in a struct msghdr. */ +struct cmsghdr_expr { + struct expression *cmsg_len; + struct expression *cmsg_level; + struct expression *cmsg_type; + struct expression *cmsg_data; +}; + /* Parse tree for a pollfd struct in a poll syscall. */ struct pollfd_expr { struct expression *fd; /* file descriptor */ @@ -274,6 +286,7 @@ struct sctp_sndinfo_expr { struct expression *snd_flags; struct expression *snd_ppid; struct expression *snd_context; + struct expression *snd_assoc_id; }; /* Parse tree for sctp_setadaptation struct in [gs]etsockopt syscall. */ diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c index 9b0bc90bc370a39d4290c88fcd923801218762ad..b8d5288ba0690bbab275a8ebdce2e20e5ccc7cc0 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -82,6 +82,7 @@ struct int_symbol platform_symbols_table[] = { { SCTP_RTOINFO, "SCTP_RTOINFO" }, { SCTP_ASSOCINFO, "SCTP_ASSOCINFO" }, { SCTP_INITMSG, "SCTP_INITMSG" }, + { SCTP_INIT, "SCTP_INIT" }, { SCTP_NODELAY, "SCTP_NODELAY" }, { SCTP_ADAPTATION_LAYER, "SCTP_ADAPTATION_LAYER" }, { SCTP_MAXSEG, "SCTP_MAXSEG" }, @@ -221,6 +222,11 @@ struct int_symbol platform_symbols_table[] = { { SCTP_ADDR_UNREACHABLE, "SCTP_ADDR_UNREACHABLE" }, { SCTP_ADDR_REMOVED, "SCTP_ADDR_REMOVED" }, { SCTP_ADDR_MADE_PRIM, "SCTP_ADDR_MADE_PRIM" }, + { SCTP_SNDINFO, "SCTP_SNDINFO" }, + { SCTP_PRINFO, "SCTP_PRINFO" }, + { SCTP_AUTHINFO, "SCTP_AUTHINFO" }, + { SCTP_DSTADDRV4, "SCTP_DSTADDRV4" }, + { SCTP_DSTADDRV6, "SCTP_DSTADDRV6" }, /* /usr/include/netinet/tcp.h */ { TCP_NODELAY, "TCP_NODELAY" }, { TCP_MAXSEG, "TCP_MAXSEG" }, 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 index 2b9f57a45ab668a1797af277c6744b7bd6fe6933..a33a6d1950fec9df17d13a79b78dd047d694a1fb 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt @@ -115,14 +115,14 @@ sasoc_cookie_life=...}, [20]) = 0 +0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=1}, 8) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=1}, [8]) = 0 -+0 setsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=0, snd_ppid=htonl(1), snd_context=1}, 16) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=0, snd_ppid=htonl(1), snd_context=1}, [16]) = 0 -+0 setsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2}, 16) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2}, [16]) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=...}, [16]) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=..., snd_context=2}, [16]) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=..., snd_ppid=htonl(2), snd_context=2}, [16]) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=..., snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2}, [16]) = 0 ++0 setsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=0, snd_ppid=htonl(1), snd_context=1, snd_assoc_id=0}, 16) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=0, snd_ppid=htonl(1), snd_context=1, snd_assoc_id=0}, [16]) = 0 ++0 setsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2, snd_assoc_id=0}, 16) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2, snd_assoc_id=0}, [16]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=..., snd_assoc_id=0}, [16]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=..., snd_context=2, snd_assoc_id=0},[16]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=..., snd_ppid=htonl(2), snd_context=2, snd_assoc_id=0}, [16]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=..., snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2, snd_assoc_id=0}, [16]) = 0 +0 setsockopt(3, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, {ssb_adaptation_ind=2}, 4) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, {ssb_adaptation_ind=2}, [4]) = 0 diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt index 114a476808ae46fa799c0b32ea28b879eb416d27..b5dbb6f097c0a049c4684c5c3dda42f80115b8f8 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt @@ -50,14 +50,15 @@ //test with all sctp_sendv_spainfo +1.0 sctp_sendv(3, [{..., 500}, {..., 500}], 2, ..., 1, {sendv_flags=SCTP_SEND_SNDINFO_VALID, -sendv_sndinfo={snd_sid=2, snd_flags=0, snd_ppid=htonl(0), snd_context=0}, +sendv_sndinfo={snd_sid=2, snd_flags=0, snd_ppid=htonl(0), snd_context=0, snd_assoc_id=0}, sendv_prinfo={pr_policy=SCTP_PR_SCTP_TTL, pr_value=10}, sendv_authinfo={auth_keynumber=123}}, 32, SCTP_SENDV_SPA, 0) = 1000 * > sctp: DATA[flgs=BE, len=1016, tsn=8, sid=2, ssn=0, ppid=0] +0.0 < sctp: SACK[flgs=0, cum_tsn=8, a_rwnd=1500, gaps=[], dups=[]] //test with sctp_sendv_sndinfo -+1.0 sctp_sendv(3, [{iov_base=..., iov_len=1000}], 1, ..., 1, {snd_sid=1, snd_flags=0, snd_ppid=htonl(1234), snd_context=0}, 16, SCTP_SENDV_SNDINFO, 0) = 1000 ++1.0 sctp_sendv(3, [{iov_base=..., iov_len=1000}], 1, ..., 1, {snd_sid=1, snd_flags=0, snd_ppid=htonl(1234), snd_context=0, snd_assoc_id=0}, 16, SCTP_SENDV_SNDINFO, 0) += 1000 * > sctp: DATA[flgs=BE, len=1016, tsn=9, sid=1, ssn=0, ppid=1234] +0.0 < sctp: SACK[flgs=0, cum_tsn=9, a_rwnd=1500, gaps=[], dups=[]]