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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