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 11c877cc..fc37ee87 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 a2d6e31a..daf88f6a 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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νz>LTNkj#zj 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