From d45db0f5af0ff7ede3b16a8f44d45e8dfedadb0a Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Wed, 14 Oct 2015 15:46:22 -0400 Subject: [PATCH] Fixed premature connection close bug --- netcon/Intercept.c | 160 ++++++++++++++++++++--------------- netcon/NetconEthernetTap.cpp | 26 ++---- netcon/libintercept.so.1.0 | Bin 0 -> 46280 bytes 3 files changed, 99 insertions(+), 87 deletions(-) create mode 100755 netcon/libintercept.so.1.0 diff --git a/netcon/Intercept.c b/netcon/Intercept.c index 97af0c94a..e813c986c 100755 --- a/netcon/Intercept.c +++ b/netcon/Intercept.c @@ -327,6 +327,7 @@ void set_up_intercept() ------------------------- ioctl(), fcntl(), setsockopt()------------------------ ------------------------------------------------------------------------------*/ +/* char *cmd_to_str(int cmd) { switch(cmd) @@ -352,7 +353,8 @@ char *cmd_to_str(int cmd) } return "?"; } - +*/ +/* void arg_to_str(int arg) { if(arg & O_RDONLY) dwr("O_RDONLY "); @@ -370,7 +372,8 @@ void arg_to_str(int arg) if(arg & O_DSYNC) dwr("O_DSYNC "); if(arg & O_SYNC) dwr("O_SYNC "); } - +*/ +/* char* level_to_str(int level) { switch(level) @@ -384,7 +387,8 @@ char* level_to_str(int level) } return "?"; } - +*/ +/* char* option_name_to_str(int opt) { if(opt == SO_DEBUG) return "SO_DEBUG"; @@ -403,6 +407,62 @@ char* option_name_to_str(int opt) if(opt == SO_SNDTIMEO)return "SO_SNDTIMEO"; return "?"; } +*/ + +/*------------------------------------------------------------------------------ +---------------------------------- shutdown() ---------------------------------- +------------------------------------------------------------------------------*/ + +/* +void shutdown_arg_to_str(int arg) +{ + if(arg & O_RDONLY) dwr("O_RDONLY "); + if(arg & O_WRONLY) dwr("O_WRONLY "); + if(arg & O_RDWR) dwr("O_RDWR "); + if(arg & O_CREAT) dwr("O_CREAT "); + if(arg & O_EXCL) dwr("O_EXCL "); + if(arg & O_NOCTTY) dwr("O_NOCTTY "); + if(arg & O_TRUNC) dwr("O_TRUNC "); + if(arg & O_APPEND) dwr("O_APPEND "); + if(arg & O_ASYNC) dwr("O_ASYNC "); + if(arg & O_DIRECT) dwr("O_DIRECT "); + if(arg & O_NOATIME) dwr("O_NOATIME "); + if(arg & O_NONBLOCK) dwr("O_NONBLOCK "); + if(arg & O_DSYNC) dwr("O_DSYNC "); + if(arg & O_SYNC) dwr("O_SYNC "); +} +*/ + +/* +void sock_type_to_str(int arg) +{ + if(arg == SOCK_STREAM) printf("SOCK_STREAM "); + if(arg == SOCK_DGRAM) printf("SOCK_DGRAM "); + if(arg == SOCK_SEQPACKET) printf("SOCK_SEQPACKET "); + if(arg == SOCK_RAW) printf("SOCK_RAW "); + if(arg == SOCK_RDM) printf("SOCK_RDM "); + if(arg == SOCK_PACKET) printf("SOCK_PACKET "); + if(arg & SOCK_NONBLOCK) printf("| SOCK_NONBLOCK "); + if(arg & SOCK_CLOEXEC) printf("| SOCK_CLOEXEC "); +} +*/ + +/* +void sock_domain_to_str(int domain) +{ + if(domain == AF_UNIX) printf("AF_UNIX "); + if(domain == AF_LOCAL) printf("AF_LOCAL "); + if(domain == AF_INET) printf("AF_INET "); + if(domain == AF_INET6) printf("AF_INET6 "); + if(domain == AF_IPX) printf("AF_IPX "); + if(domain == AF_NETLINK) printf("AF_NETLINK "); + if(domain == AF_X25) printf("AF_X25 "); + if(domain == AF_AX25) printf("AF_AX25 "); + if(domain == AF_ATMPVC) printf("AF_ATMPVC "); + if(domain == AF_APPLETALK) printf("AF_APPLETALK "); + if(domain == AF_PACKET) printf("AF_PACKET "); +} +*/ /*------------------------------------------------------------------------------ --------------------------------- setsockopt() --------------------------------- @@ -458,59 +518,10 @@ int getsockopt(GETSOCKOPT_SIG) } -/*------------------------------------------------------------------------------ ----------------------------------- shutdown() ---------------------------------- -------------------------------------------------------------------------------*/ - -void shutdown_arg_to_str(int arg) -{ - if(arg & O_RDONLY) dwr("O_RDONLY "); - if(arg & O_WRONLY) dwr("O_WRONLY "); - if(arg & O_RDWR) dwr("O_RDWR "); - if(arg & O_CREAT) dwr("O_CREAT "); - if(arg & O_EXCL) dwr("O_EXCL "); - if(arg & O_NOCTTY) dwr("O_NOCTTY "); - if(arg & O_TRUNC) dwr("O_TRUNC "); - if(arg & O_APPEND) dwr("O_APPEND "); - if(arg & O_ASYNC) dwr("O_ASYNC "); - if(arg & O_DIRECT) dwr("O_DIRECT "); - if(arg & O_NOATIME) dwr("O_NOATIME "); - if(arg & O_NONBLOCK) dwr("O_NONBLOCK "); - if(arg & O_DSYNC) dwr("O_DSYNC "); - if(arg & O_SYNC) dwr("O_SYNC "); -} - /*------------------------------------------------------------------------------ ----------------------------------- socket() ----------------------------------- ------------------------------------------------------------------------------*/ -void sock_type_to_str(int arg) -{ - if(arg == SOCK_STREAM) printf("SOCK_STREAM "); - if(arg == SOCK_DGRAM) printf("SOCK_DGRAM "); - if(arg == SOCK_SEQPACKET) printf("SOCK_SEQPACKET "); - if(arg == SOCK_RAW) printf("SOCK_RAW "); - if(arg == SOCK_RDM) printf("SOCK_RDM "); - if(arg == SOCK_PACKET) printf("SOCK_PACKET "); - if(arg & SOCK_NONBLOCK) printf("| SOCK_NONBLOCK "); - if(arg & SOCK_CLOEXEC) printf("| SOCK_CLOEXEC "); -} - -void sock_domain_to_str(int domain) -{ - if(domain == AF_UNIX) printf("AF_UNIX "); - if(domain == AF_LOCAL) printf("AF_LOCAL "); - if(domain == AF_INET) printf("AF_INET "); - if(domain == AF_INET6) printf("AF_INET6 "); - if(domain == AF_IPX) printf("AF_IPX "); - if(domain == AF_NETLINK) printf("AF_NETLINK "); - if(domain == AF_X25) printf("AF_X25 "); - if(domain == AF_AX25) printf("AF_AX25 "); - if(domain == AF_ATMPVC) printf("AF_ATMPVC "); - if(domain == AF_APPLETALK) printf("AF_APPLETALK "); - if(domain == AF_PACKET) printf("AF_PACKET "); -} - /* int socket_family, int socket_type, int protocol socket() intercept function */ @@ -520,14 +531,20 @@ int socket(SOCKET_SIG) #ifdef CHECKS /* Check that type makes sense */ int flags = socket_type & ~SOCK_TYPE_MASK; - if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) - return -EINVAL; + if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) { + errno = EINVAL; + return -1; + } socket_type &= SOCK_TYPE_MASK; /* Check protocol is in range */ - if (socket_family < 0 || socket_family >= NPROTO) - return -EAFNOSUPPORT; - if (socket_type < 0 || socket_type >= SOCK_MAX) - return -EINVAL; + if (socket_family < 0 || socket_family >= NPROTO){ + errno = EAFNOSUPPORT; + return -1; + } + if (socket_type < 0 || socket_type >= SOCK_MAX) { + errno = EINVAL; + return -1; + } /* Check that we haven't hit the soft-limit file descriptors allowed */ /* FIXME: Find number of open fds struct rlimit rl; @@ -565,12 +582,12 @@ int socket(SOCKET_SIG) cmd[0] = RPC_SOCKET; memcpy(&cmd[1], &rpc_st, sizeof(struct socket_st)); pthread_mutex_lock(&lock); - write(fdret_sock,cmd, BUF_SZ); + send_command(fdret_sock, cmd); /* get new fd */ - char gmybuf[16]; - ssize_t size = sock_fd_read(fdret_sock, gmybuf, sizeof(gmybuf), &newfd); - if(size > 0) + char rbuf[16]; + ssize_t sz = sock_fd_read(fdret_sock, rbuf, sizeof(rbuf), &newfd); + if(sz > 0) { /* send our local-fd number back to service so it can complete its mapping table entry */ @@ -780,8 +797,10 @@ int bind(BIND_SIG) int accept4(ACCEPT4_SIG) { #ifdef CHECKS - if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) - return -EINVAL; + if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) { + errno = EINVAL; + return -1; + } #endif #ifdef DUMMY dwr("accept4(%d)\n", sockfd); @@ -843,11 +862,12 @@ int accept(ACCEPT_SIG) return -1; } - char gmybuf[16], c[1]; - int new_conn_socket, n = read(sockfd, c, sizeof(c)); + char rbuf[16], c[1]; + int new_conn_socket; + int n = read(sockfd, c, sizeof(c)); // Read signal byte if(n > 0) { - ssize_t size = sock_fd_read(fdret_sock, gmybuf, sizeof(gmybuf), &new_conn_socket); + ssize_t size = sock_fd_read(fdret_sock, rbuf, sizeof(rbuf), &new_conn_socket); if(size > 0) { /* Send our local-fd number back to service so it can complete its mapping table */ memset(cmd, '\0', BUF_SZ); @@ -857,7 +877,7 @@ int accept(ACCEPT_SIG) int n_write = write(fdret_sock, cmd, BUF_SZ); if(n_write < 0) { dwr("Error sending perceived FD to service.\n"); - errno = ECONNABORTED; + errno = ECONNABORTED; // FIXME: Closest match, service unreachable return -1; } pthread_mutex_unlock(&lock); @@ -866,13 +886,13 @@ int accept(ACCEPT_SIG) } else { dwr("Error receiving new FD from service.\n"); - errno = ECONNABORTED; + errno = ECONNABORTED; // FIXME: Closest match, service unreachable return -1; } } dwr("Error reading signal byte from service.\n"); //errno = EWOULDBLOCK; - errno = ECONNABORTED; + errno = ECONNABORTED; // FIXME: Closest match, service unreachable return -1; #endif } diff --git a/netcon/NetconEthernetTap.cpp b/netcon/NetconEthernetTap.cpp index 9d763463e..9aa9def0d 100644 --- a/netcon/NetconEthernetTap.cpp +++ b/netcon/NetconEthernetTap.cpp @@ -265,20 +265,21 @@ TcpConnection *NetconEthernetTap::getConnectionByTheirFD(PhySocket *sock, int fd */ void NetconEthernetTap::closeConnection(TcpConnection *conn) { - //fprintf(stderr, "closeConnection(): closing: conn->type = %d, fd=%d\n", conn->type, _phy.getDescriptor(conn->sock)); lwipstack->_tcp_arg(conn->pcb, NULL); lwipstack->_tcp_sent(conn->pcb, NULL); lwipstack->_tcp_recv(conn->pcb, NULL); lwipstack->_tcp_err(conn->pcb, NULL); lwipstack->_tcp_poll(conn->pcb, NULL, 0); lwipstack->_tcp_close(conn->pcb); - close(_phy.getDescriptor(conn->dataSock)); close(conn->their_fd); - _phy.close(conn->dataSock); - + if(conn->dataSock) { + close(_phy.getDescriptor(conn->dataSock)); + _phy.close(conn->dataSock); + } for(int i=0; i_lock); - handle_write(conn); + if(conn->dataSock) // Sometimes a connection may be closed via nc_recved, check first + handle_write(conn); } else { fprintf(stderr, "phyOnFileDescriptorActivity(): PhySocket not readable\n"); @@ -504,7 +506,7 @@ int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0) [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 - Socket is not listening for connections, or addrlen is invalid (e.g., is negative). [I] EINVAL - (accept4()) invalid value in flags. [I] 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. @@ -583,7 +585,6 @@ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err) */ err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { - //fprintf(stderr, "nc_recved()\n"); Larg *l = (Larg*)arg; int n; struct pbuf* q = p; @@ -1095,22 +1096,13 @@ void NetconEthernetTap::handle_write(TcpConnection *conn) /* PCB send buffer is full,turn off readability notifications for the corresponding PhySocket until nc_sent() is called and confirms that there is now space on the buffer */ - if(sndbuf == 0) { _phy.setNotifyReadable(conn->dataSock, false); lwipstack->_tcp_output(conn->pcb); return; } -/* - if(conn->dataSock == NULL) - { - fprintf(stderr, "their_fd = %d, perc_fd = %d\n", conn->their_fd, conn->perceived_fd); - fprintf(stderr, "No dataSock assigned\n"); - exit(1); - } -*/ - int read_fd = _phy.getDescriptor(conn->dataSock); + int read_fd = _phy.getDescriptor(conn->dataSock); if((r = read(read_fd, (&conn->buf)+conn->idx, sndbuf)) > 0) { conn->idx += r; /* Writes data pulled from the client's socket buffer to LWIP. This merely sends the diff --git a/netcon/libintercept.so.1.0 b/netcon/libintercept.so.1.0 new file mode 100755 index 0000000000000000000000000000000000000000..5b9c3f31e89b8e1367d48abd39630483d1d4b68b GIT binary patch literal 46280 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