From 402302ead0690b6a3e3202a5680ea1f398cbaa61 Mon Sep 17 00:00:00 2001
From: hoelscher <jens.hoelscher@fh-muenster.de>
Date: Tue, 22 Sep 2015 00:28:29 +0200
Subject: [PATCH] Add parser for getsockopt SO_LINGER with Ellipse and Integer

---
 gtests/net/packetdrill/parser.y               | 37 ++++++++++---
 gtests/net/packetdrill/run_system_call.c      | 52 +++++++++++++------
 gtests/net/packetdrill/script.c               |  4 ++
 gtests/net/packetdrill/script.h               |  8 ++-
 .../bsd/sctp/sctp_get_socket_options.pkt      | 12 ++---
 5 files changed, 83 insertions(+), 30 deletions(-)

diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index a8aa4236..706395d0 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -564,7 +564,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
-%type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents linger
+%type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents 
+%type <expression> linger l_onoff l_linger
 %type <expression> sctp_rtoinfo sctp_initmsg sctp_assocval sctp_sackinfo
 %type <expression> sctp_status
 %type <errno_info> opt_errno
@@ -2276,15 +2277,39 @@ pollfd
 ;
 
 opt_revents
-:                                { $$ = new_integer_expression(0, "%ld"); }
+:                                { $$ = new_integer_expression(0, "%ld" ); }
 | ',' REVENTS '=' expression     { $$ = $4; }
 ;
 
+l_onoff
+: ONOFF '=' INTEGER  { 
+	if (!is_valid_u32($3)){
+		semantic_error("linger onoff out of range");
+	} else {
+		printf("test2\n");
+		$$ = new_integer_expression( $3, "%ld" ); 
+	}	
+}
+| ONOFF '=' ELLIPSIS { $$ = new_expression( EXPR_ELLIPSIS ); }
+;
+
+l_linger
+: LINGER '=' INTEGER  { 
+	if (!is_valid_u32($3)){
+		semantic_error("linger out of range");
+	}
+	$$ = new_integer_expression( $3, "%ld");
+	printf("test6\n"); 
+}
+| LINGER '=' ELLIPSIS { $$ = new_expression( EXPR_ELLIPSIS ); }
+;
+
 linger
-: '{' ONOFF '=' INTEGER ',' LINGER '=' INTEGER '}' {
-	$$ = new_expression(EXPR_LINGER);
-	$$->value.linger.l_onoff  = $4;
-	$$->value.linger.l_linger = $8;
+: '{' l_onoff ',' l_linger '}' {
+	$$ = new_expression( EXPR_LINGER );
+	$$->value.linger = (struct linger_expr*) malloc(sizeof(struct linger_expr));
+	$$->value.linger->l_onoff  = $2;
+	$$->value.linger->l_linger = $4;
 }
 ;
 
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 6f5a018b..5e98c2a0 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -1582,8 +1582,9 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 	if (val_expression == NULL) {
 		return STATUS_ERR;
 	} else if (val_expression->type == EXPR_LINGER) {
-		live_optval = malloc(sizeof(val_expression->value.linger));
-		live_optlen = (socklen_t)sizeof(val_expression->value.linger);
+		printf("3\n");
+		live_optval = malloc(sizeof(struct linger));
+		live_optlen = (socklen_t)sizeof(struct linger);
 #ifdef SCTP_RTOINFO
 	} else if (val_expression->type == EXPR_SCTP_RTOINFO) {
 		live_optval = malloc(sizeof(val_expression->value.sctp_rtoinfo));
@@ -1614,21 +1615,38 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall,
 		free(live_optval);
 		return STATUS_ERR;
 	}
-
 	if (val_expression->type == EXPR_LINGER) {
+		struct expression *l_onoff = val_expression->value.linger->l_onoff;
+		struct expression *l_linger = val_expression->value.linger->l_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: %d",
-			         val_expression->value.linger.l_onoff, ling->l_onoff);
-			free(live_optval);
-			return STATUS_ERR;
+		int val_onoff = 0; 
+		if(l_onoff->type == EXPR_INTEGER){
+			if(get_s32(l_onoff, &val_onoff, error)){
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			printf("Start Auswertung Linger\n");
+			if (val_onoff != ling->l_onoff) {
+				asprintf(error, "Bad getsockopt Linger onoff: expected: %d actual: %d",
+			         	(int) val_onoff, ling->l_onoff);
+				free(live_optval);
+				return STATUS_ERR;
+			}
 		}
-		if (ling->l_linger != val_expression->value.linger.l_linger) {
-			asprintf(error, "Bad getsockopt Linger Value: expected: %d actual: %d",
-			         val_expression->value.linger.l_linger, ling->l_linger);
-			free(live_optval);
-			return STATUS_ERR;
+		int val_linger = 0;
+		if(l_linger->type == EXPR_INTEGER){
+			if(get_s32(l_linger, &val_linger, error)){
+				free(live_optval);
+				return STATUS_ERR;
+			}
+			if (ling->l_linger != val_linger) {
+				asprintf(error, "Bad getsockopt Linger Value: expected: %d actual: %d",
+			        	 val_linger, ling->l_linger);
+				free(live_optval);
+				return STATUS_ERR;
+			}
 		}
+
 #ifdef SCTP_RTOINFO
 	} else if (val_expression->type == EXPR_SCTP_RTOINFO) {
 		struct sctp_rtoinfo *rtoinfo = live_optval;
@@ -1708,7 +1726,6 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 	int script_fd, live_fd, level, optname, optval_s32, optlen, result;
 	void *optval = NULL;
 	struct expression *val_expression;
-
 	if (check_arg_count(args, 5, error))
 		return STATUS_ERR;
 	if (s32_arg(args, 0, &script_fd, error))
@@ -1726,7 +1743,11 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 	if (val_expression == NULL)
 		return STATUS_ERR;
 	if (val_expression->type == EXPR_LINGER) {
-		optval = &val_expression->value.linger;
+		optval = malloc( sizeof( struct linger ));
+		get_s32(val_expression->value.linger->l_onoff, 
+			&(((struct linger*) optval)->l_onoff), error);
+		get_s32(val_expression->value.linger->l_linger,
+                        &(((struct linger*) optval)->l_linger), error);
 	} else if (val_expression->type == EXPR_STRING) {
 		optval = val_expression->value.string;
 	} else if (val_expression->type == EXPR_LIST) {
@@ -1765,6 +1786,7 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall,
 	result = setsockopt(live_fd, level, optname, optval, optlen);
 
 	return end_syscall(state, syscall, CHECK_EXACT, result, error);
+	free(optval);
 }
 
 static int syscall_poll(struct state *state, struct syscall_spec *syscall,
diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c
index c4fdb4b2..3547414b 100644
--- a/gtests/net/packetdrill/script.c
+++ b/gtests/net/packetdrill/script.c
@@ -285,7 +285,11 @@ void free_expression(struct expression *expression)
 	switch (expression->type) {
 	case EXPR_ELLIPSIS:
 	case EXPR_INTEGER:
+		break;
 	case EXPR_LINGER:
+                free(expression->value.linger->l_onoff);
+                free(expression->value.linger->l_linger);
+                break;
 #ifdef SCTP_RTOINFO
 	case EXPR_SCTP_RTOINFO:
 #endif
diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h
index a2b2e46b..38b458dc 100644
--- a/gtests/net/packetdrill/script.h
+++ b/gtests/net/packetdrill/script.h
@@ -72,7 +72,7 @@ struct expression {
 	union {
 		s64 num;
 		char *string;
-		struct linger linger;
+		struct linger_expr *linger;
 		struct sockaddr_in *socket_address_ipv4;
 		struct sockaddr_in6 *socket_address_ipv6;
 		struct binary_expression *binary;
@@ -136,6 +136,12 @@ struct pollfd_expr {
 	struct expression *revents;	/* returned events */
 };
 
+/* Handle the values for socketoption SO_Linger with inputtypes and values*/
+struct linger_expr {
+	struct expression *l_onoff;
+	struct expression *l_linger;
+};
+
 /* 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/tests/bsd/sctp/sctp_get_socket_options.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt
index 8799fc15..57604f83 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
@@ -10,18 +10,14 @@
 
 +0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 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 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 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=..., linger=30}, [8]) = 0
-+0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=128, linger=...}, [8]) = 0
-+0 getsockopt(3, SOL_SOCKET, SO_LINGER, {onoff=..., linger=...}, [8]) = 0
-
+ 		sstat_fragmentation_point=1452, sstat_primary=...}, [176])= 0
 
 +0 close(3) = 0
 
-- 
GitLab