From 8d1b01cb5b6b5e5903f873ba82e329e723f78b98 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Mon, 12 Oct 2015 20:46:59 -0400 Subject: [PATCH] Bug fix: Connection fd lookup in service --- netcon/NetconEthernetTap.cpp | 129 +++++++++++++++++++++++++++++++---- netcon/NetconEthernetTap.hpp | 2 +- netcon/intercept.c | 25 ++++--- netcon/libintercept.so.1.0 | Bin 52032 -> 0 bytes 4 files changed, 127 insertions(+), 29 deletions(-) delete mode 100755 netcon/libintercept.so.1.0 diff --git a/netcon/NetconEthernetTap.cpp b/netcon/NetconEthernetTap.cpp index 53dfe3f03..0e2599eab 100644 --- a/netcon/NetconEthernetTap.cpp +++ b/netcon/NetconEthernetTap.cpp @@ -252,10 +252,10 @@ TcpConnection *NetconEthernetTap::getConnectionByPCB(struct tcp_pcb *pcb) return NULL; } -TcpConnection *NetconEthernetTap::getConnectionByTheirFD(int fd) +TcpConnection *NetconEthernetTap::getConnectionByTheirFD(PhySocket *sock, int fd) { for(size_t i=0; iperceived_fd == fd) + if(tcp_connections[i]->perceived_fd == fd && tcp_connections[i]->rpcSock == sock) return tcp_connections[i]; } return NULL; @@ -498,16 +498,16 @@ int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0) this case, and does not require these constants to have the same value, so a portable application should check for both possibilities. [ ] EBADF - The descriptor is invalid. - [?] ECONNABORTED - A connection has been aborted. - [ ] EFAULT - The addr argument is not in a writable part of the user address space. + [i] ECONNABORTED - A connection has been aborted. + [i] EFAULT - The addr argument is not in a writable part of the user address space. [ ] EINTR - The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7). [ ] EINVAL - Socket is not listening for connections, or addrlen is invalid (e.g., is negative). [ ] EINVAL - (accept4()) invalid value in flags. [ ] EMFILE - The per-process limit of open file descriptors has been reached. [ ] ENFILE - The system limit on the total number of open files has been reached. [ ] ENOBUFS, ENOMEM - Not enough free memory. This often means that the memory allocation is limited by the socket buffer limits, not by the system memory. - [ ] ENOTSOCK - The descriptor references a file, not a socket. - [ ] EOPNOTSUPP - The referenced socket is not of type SOCK_STREAM. + [i] ENOTSOCK - The descriptor references a file, not a socket. + [i] EOPNOTSUPP - The referenced socket is not of type SOCK_STREAM. [ ] EPROTO - Protocol error. * @@ -625,9 +625,66 @@ err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf */ void NetconEthernetTap::nc_err(void *arg, err_t err) { - //fprintf(stderr, "nc_err\n"); Larg *l = (Larg*)arg; + fprintf(stderr, "larg = %x, nc_err() = %d\n", l, err); + if(l->conn) { + switch(err) + { + // FIXME: Check if connection is pending first? + + case ERR_MEM: + l->tap->send_return_value(l->conn, -1, ENOMEM); + break; + case ERR_BUF: + // FIXME: From user's perspective, this is the same as an ENOMEM error. I think. + l->tap->send_return_value(l->conn, -1, ENOMEM); + break; + case ERR_TIMEOUT: + l->tap->send_return_value(l->conn, -1, ETIMEDOUT); + break; + case ERR_RTE: + l->tap->send_return_value(l->conn, -1, ENETUNREACH); + break; + case ERR_INPROGRESS: + l->tap->send_return_value(l->conn, -1, EINPROGRESS); + break; + case ERR_VAL: + l->tap->send_return_value(l->conn, -1, EINVAL); + break; + case ERR_WOULDBLOCK: + l->tap->send_return_value(l->conn, -1, EWOULDBLOCK); + break; + case ERR_USE: + l->tap->send_return_value(l->conn, -1, EADDRINUSE); + break; + case ERR_ISCONN: + l->tap->send_return_value(l->conn, -1, EISCONN); + 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; + case ERR_CLSD: + l->tap->send_return_value(l->conn, -1, -1); + break; + case ERR_CONN: + l->tap->send_return_value(l->conn, -1, -1); + break; + case ERR_ARG: + l->tap->send_return_value(l->conn, -1, -1); + break; + case ERR_IF: + l->tap->send_return_value(l->conn, -1, -1); + break; + default: + break; + } fprintf(stderr, "nc_err(): closing connection\n"); l->tap->closeConnection(l->conn); } @@ -741,7 +798,8 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st int conn_port = lwipstack->ntohs(connaddr->sin_port); ip_addr_t conn_addr; conn_addr.addr = *((u32_t *)_ips[0].rawIpData()); - TcpConnection *conn = getConnectionByTheirFD(bind_rpc->sockfd); + + TcpConnection *conn = getConnectionByTheirFD(sock, bind_rpc->sockfd); if(conn) { if(conn->pcb->state == CLOSED){ @@ -789,7 +847,7 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st */ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct listen_st *listen_rpc) { - TcpConnection *conn = getConnectionByTheirFD(listen_rpc->sockfd); + TcpConnection *conn = getConnectionByTheirFD(sock, listen_rpc->sockfd); if(conn) { if(conn->pcb->state == LISTEN) { fprintf(stderr, "handle_listen(): PCB is already in listening state.\n"); @@ -850,12 +908,12 @@ void NetconEthernetTap::handle_retval(PhySocket *sock, void **uptr, unsigned cha TODO: set errno appropriately [ ] EACCES - Permission to create a socket of the specified type and/or protocol is denied. - [ ] EAFNOSUPPORT - The implementation does not support the specified address family. - [ ] EINVAL - Unknown protocol, or protocol family not available. - [ ] EINVAL - Invalid flags in type. + [?] EAFNOSUPPORT - The implementation does not support the specified address family. + [?] EINVAL - Unknown protocol, or protocol family not available. + [?] EINVAL - Invalid flags in type. [ ] EMFILE - Process file table overflow. [ ] ENFILE - The system limit on the total number of open files has been reached. - [ ] ENOBUFS or ENOMEM - Insufficient memory is available. The socket cannot be created until sufficient resources are freed. + [X] ENOBUFS or ENOMEM - Insufficient memory is available. The socket cannot be created until sufficient resources are freed. [ ] EPROTONOSUPPORT - The protocol type or the specified protocol is not supported within this domain. */ @@ -891,6 +949,26 @@ void NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socke * * @param Client that is making the RPC * @param structure containing the data and parameters for this client's RPC + + --- Error handling in this method will only catch problems which are immeidately + apprent. Some errors will need to be caught in the nc_connected(0 callback + + [i] EACCES - For UNIX domain sockets, which are identified by pathname: Write permission is denied ... + [ ] EACCES, EPERM - The user tried to connect to a broadcast address without having the socket broadcast flag enabled ... + [i] EADDRINUSE - Local address is already in use. + [?] EAFNOSUPPORT - The passed address didn't have the correct address family in its sa_family field. + [ ] EAGAIN - No more free local ports or insufficient entries in the routing cache. + [ ] EALREADY - The socket is nonblocking and a previous connection attempt has not yet been completed. + [ ] EBADF - The file descriptor is not a valid index in the descriptor table. + [ ] ECONNREFUSED - No-one listening on the remote address. + [i] EFAULT - The socket structure address is outside the user's address space. + [ ] EINPROGRESS - The socket is nonblocking and the connection cannot be completed immediately. + [ ] EINTR - The system call was interrupted by a signal that was caught. + [X] EISCONN - The socket is already connected. + [?] ENETUNREACH - Network is unreachable. + [ ] ENOTSOCK - The file descriptor is not associated with a socket. + [ ] ETIMEDOUT - Timeout while attempting connection. + * */ void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct connect_st* connect_rpc) @@ -911,7 +989,27 @@ void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct conn int err = 0; if((err = lwipstack->tcp_connect(conn->pcb,&conn_addr,conn_port, nc_connected)) < 0) { - fprintf(stderr, "handle_connect(): unable to connect\n"); + if(err == ERR_USE) { + send_return_value(conn, -1, EISCONN); // Already in use + return; + } + if(err == ERR_VAL) { + send_return_value(conn, -1, EAFNOSUPPORT); // FIXME: Invalid arguments? + return; + } + if(err == ERR_RTE) { + send_return_value(conn, -1, ENETUNREACH); // FIXME: Host unreachable + return; + } + if(err == ERR_BUF) + { + // FIXME + } + if(err == ERR_MEM) + { + // FIXME: return value originates from tcp_enqueue_flags() + } + // We should only return a value if failure happens immediately // Otherwise, we still need to wait for a callback from lwIP. // - This is because an ERR_OK from tcp_connect() only verifies @@ -919,7 +1017,8 @@ void NetconEthernetTap::handle_connect(PhySocket *sock, void **uptr, struct conn // that's it! // - Most instances of a retval for a connect() should happen // in the nc_connect() and nc_err() callbacks! - send_return_value(conn, err); + fprintf(stderr, "handle_connect(): unable to connect\n"); + send_return_value(conn, -1, err); // FIXME: Only catch unhandled errors } // Everything seems to be ok, but we don't have enough info to retval conn->pending=true; diff --git a/netcon/NetconEthernetTap.hpp b/netcon/NetconEthernetTap.hpp index 6bf2596e0..f10761db7 100644 --- a/netcon/NetconEthernetTap.hpp +++ b/netcon/NetconEthernetTap.hpp @@ -139,7 +139,7 @@ private: } // Client helpers - TcpConnection *getConnectionByTheirFD(int fd); + TcpConnection *getConnectionByTheirFD(PhySocket *sock, int fd); TcpConnection *getConnectionByPCB(struct tcp_pcb *pcb); void closeConnection(TcpConnection *conn); void closeAll(); diff --git a/netcon/intercept.c b/netcon/intercept.c index df2dc7cfc..f4fff1f9f 100755 --- a/netcon/intercept.c +++ b/netcon/intercept.c @@ -174,14 +174,11 @@ int get_retval() memcpy(&errno, &retbuf[1+sizeof(retval)], sizeof(errno)); return retval; } - else { - dwr("unable to read connect: return value\n"); - return -1; - } } + dwr("unable to read connect: return value\n"); + return -1; } -#define SLEEP_TIME 0 /*------------------------------------------------------------------------------ ---------- Unix-domain socket lazy initializer (for fd-transfers)-------------- @@ -190,7 +187,6 @@ int get_retval() /* Sets up the connection pipes and sockets to the service */ int init_service_connection() { - usleep(SLEEP_TIME); if(!is_initialized) { struct sockaddr_un addr; @@ -515,10 +511,12 @@ int socket(SOCKET_SIG) if(socket_family == AF_LOCAL || socket_family == AF_NETLINK || socket_family == AF_UNIX) { - int err = realsocket(socket_family, socket_type, protocol); - return err; + return realsocket(socket_family, socket_type, protocol); } + /* FIXME: Check type, protocol, return EINVAL errno */ + /* FIXME: Check family, return EAFNOSUPPORT errno */ + /* Assemble and route command */ struct socket_st rpc_st; rpc_st.socket_family = socket_family; @@ -549,7 +547,7 @@ int socket(SOCKET_SIG) return get_retval(); } pthread_mutex_unlock(&lock); - errno = ERR_OK; + errno = ERR_OK; // OK return newfd; } else { // Try to read retval+errno since we RXed a bad fd @@ -562,7 +560,6 @@ int socket(SOCKET_SIG) pthread_mutex_unlock(&lock); return get_retval(); } - return realsocket(socket_family, socket_type, protocol); #endif } @@ -765,6 +762,8 @@ int accept(ACCEPT_SIG) addr->sa_family = AF_INET; /* TODO: also get address info */ + /* FIXME: Check that socket is type SOCK_STREAM */ + char cmd[BUF_SZ]; if(realaccept == NULL) { dwr( "Unresolved symbol: accept()\n"); @@ -788,7 +787,7 @@ int accept(ACCEPT_SIG) pthread_mutex_lock(&lock); int n_write = write(fdret_sock, cmd, BUF_SZ); if(n_write < 0) { - dwr("Error sending perceived FD to service. Service might be down.\n"); + dwr("Error sending perceived FD to service.\n"); errno = ECONNABORTED; return -1; } @@ -797,12 +796,12 @@ int accept(ACCEPT_SIG) return new_conn_socket; // OK } else { - dwr("Error receiving new FD from service. Service might be down.\n"); + dwr("Error receiving new FD from service.\n"); errno = ECONNABORTED; return -1; } } - dwr("Error reading signal byte from service. Service might be down.\n"); + dwr("Error reading signal byte from service.\n"); //errno = EWOULDBLOCK; errno = ECONNABORTED; return -1; diff --git a/netcon/libintercept.so.1.0 b/netcon/libintercept.so.1.0 deleted file mode 100755 index e50a40c21b7699bf2d5c6087bde35036e95049b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52032 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