From da536cc3111f3da480fb52f9dba1310b60f60ce3 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 13 Oct 2015 17:37:54 -0400 Subject: [PATCH] Improved error reporting --- netcon/NetconEthernetTap.cpp | 21 +++++++++++++++---- netcon/intercept.c | 38 +++++++++++++++-------------------- netcon/libintercept.so.1.0 | Bin 52304 -> 52376 bytes 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/netcon/NetconEthernetTap.cpp b/netcon/NetconEthernetTap.cpp index 11c877cc0..fc37ee87c 100644 --- a/netcon/NetconEthernetTap.cpp +++ b/netcon/NetconEthernetTap.cpp @@ -628,7 +628,10 @@ err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf void NetconEthernetTap::nc_err(void *arg, err_t err) { Larg *l = (Larg*)arg; - fprintf(stderr, "larg = %x, nc_err() = %d\n", l, err); + //fprintf(stderr, "larg = %x, nc_err() = %d\n", l, err); + + if(!l->conn) + fprintf(stderr, "nc_err(): Connection is NULL!\n"); if(l->conn) { switch(err) @@ -636,38 +639,48 @@ void NetconEthernetTap::nc_err(void *arg, err_t err) // FIXME: Check if connection is pending first? case ERR_MEM: + fprintf(stderr, "nc_err(): ERR_MEM->ENOMEM\n"); l->tap->send_return_value(l->conn, -1, ENOMEM); break; case ERR_BUF: + fprintf(stderr, "nc_err(): ERR_BUF->ENOBUFS\n"); l->tap->send_return_value(l->conn, -1, ENOBUFS); break; case ERR_TIMEOUT: + fprintf(stderr, "nc_err(): ERR_TIMEOUT->ETIMEDOUT\n"); l->tap->send_return_value(l->conn, -1, ETIMEDOUT); break; case ERR_RTE: + fprintf(stderr, "nc_err(): ERR_RTE->ENETUNREACH\n"); l->tap->send_return_value(l->conn, -1, ENETUNREACH); break; case ERR_INPROGRESS: + fprintf(stderr, "nc_err(): ERR_INPROGRESS->EINPROGRESS\n"); l->tap->send_return_value(l->conn, -1, EINPROGRESS); break; case ERR_VAL: + fprintf(stderr, "nc_err(): ERR_VAL->EINVAL\n"); l->tap->send_return_value(l->conn, -1, EINVAL); break; case ERR_WOULDBLOCK: + fprintf(stderr, "nc_err(): ERR_WOULDBLOCK->EWOULDBLOCK\n"); l->tap->send_return_value(l->conn, -1, EWOULDBLOCK); break; case ERR_USE: + fprintf(stderr, "nc_err(): ERR_USE->EADDRINUSE\n"); l->tap->send_return_value(l->conn, -1, EADDRINUSE); break; case ERR_ISCONN: + fprintf(stderr, "nc_err(): ERR_ISCONN->EISCONN\n"); l->tap->send_return_value(l->conn, -1, EISCONN); break; + case ERR_ABRT: + fprintf(stderr, "nc_err(): ERR_ABRT->ETIMEDOUT\n"); // FIXME: Correct? + l->tap->send_return_value(l->conn, -1, ETIMEDOUT); + break; // FIXME: Below are errors which don't have a standard errno correlate - case ERR_ABRT: - l->tap->send_return_value(l->conn, -1, -1); - break; case ERR_RST: l->tap->send_return_value(l->conn, -1, -1); break; diff --git a/netcon/intercept.c b/netcon/intercept.c index a2d6e31a4..daf88f6a2 100755 --- a/netcon/intercept.c +++ b/netcon/intercept.c @@ -514,6 +514,7 @@ void sock_domain_to_str(int domain) int socket(SOCKET_SIG) { + int err; #ifdef CHECKS /* Check that type makes sense */ int flags = socket_type & ~SOCK_TYPE_MASK; @@ -572,13 +573,16 @@ int socket(SOCKET_SIG) } else { // Try to read retval+errno since we RXed a bad fd dwr("Error, service sent bad fd.\n"); - return get_retval(); + err = get_retval(); + pthread_mutex_unlock(&lock); + return err; } } else { dwr("Error while receiving new FD.\n"); + err = get_retval(); pthread_mutex_unlock(&lock); - return get_retval(); + return err; } #endif } @@ -591,7 +595,7 @@ int socket(SOCKET_SIG) connect() intercept function */ int connect(CONNECT_SIG) { - + int err; /* FIXME: Check that address is in user space, return EFAULT ? */ #ifdef DUMMY @@ -635,23 +639,9 @@ int connect(CONNECT_SIG) memcpy(&cmd[1], &rpc_st, sizeof(struct connect_st)); pthread_mutex_lock(&lock); send_command(fdret_sock, cmd); - - if(fdret_sock >= 0) { - int retval; - char mynewbuf[BUF_SZ]; - memset(&mynewbuf, '\0', sizeof(mynewbuf)); - int n_read = read(fdret_sock, &mynewbuf, sizeof(mynewbuf)); - if(n_read > 0) { - memcpy(&retval, &mynewbuf[1], sizeof(int)); - pthread_mutex_unlock(&lock); - return retval; - } - else { - pthread_mutex_unlock(&lock); - dwr("unable to read connect: return value\n"); - } - } - return -1; + err = get_retval(); + pthread_mutex_unlock(&lock); + return err; #endif } @@ -696,6 +686,7 @@ int poll(POLL_SIG) bind() intercept function */ int bind(BIND_SIG) { + int err; #ifdef DUMMY dwr("bind(%d)\n", sockfd); return realbind(sockfd, addr, addrlen); @@ -735,9 +726,10 @@ int bind(BIND_SIG) memcpy(&cmd[1], &rpc_st, sizeof(struct bind_st)); pthread_mutex_lock(&lock); send_command(fdret_sock, cmd); + err = get_retval(); pthread_mutex_unlock(&lock); errno = ERR_OK; - return get_retval(); + return err; #endif } @@ -842,6 +834,7 @@ int accept(ACCEPT_SIG) listen() intercept function */ int listen(LISTEN_SIG) { + int err; /* FIXME: Check that this socket supports listen(), return EOPNOTSUPP */ /* FIXME: Check that the provided fd is a socket, return ENOTSOCK */ @@ -865,8 +858,9 @@ int listen(LISTEN_SIG) memcpy(&cmd[1], &rpc_st, sizeof(struct listen_st)); pthread_mutex_lock(&lock); send_command(fdret_sock, cmd); + err = get_retval(); pthread_mutex_unlock(&lock); errno = ERR_OK; - return get_retval(); + return err; #endif } diff --git a/netcon/libintercept.so.1.0 b/netcon/libintercept.so.1.0 index d0b5ffda6929f9ef6626eeed7524ea566dee7051..4d8b2f198634e13413eeaedb69d91384996867bf 100755 GIT binary patch delta 15786 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 AcK`qY delta 16024 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