diff --git a/ext/lwipopts.h b/ext/lwipopts.h index 7a75e79bb..e7b78a8fc 100644 --- a/ext/lwipopts.h +++ b/ext/lwipopts.h @@ -130,7 +130,7 @@ * MEMP_NUM_RAW_PCB: Number of raw connection PCBs * (requires the LWIP_RAW option) */ -#define MEMP_NUM_RAW_PCB 32 +#define MEMP_NUM_RAW_PCB 128 /** * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One diff --git a/make-netcon.mk b/make-netcon.mk deleted file mode 100644 index 2aa797ddf..000000000 --- a/make-netcon.mk +++ /dev/null @@ -1,29 +0,0 @@ -SHCC=gcc - -# intercept-specific -intercept_CFLAGS = -c -fPIC -g -O2 -Wall -std=c99 -D_GNU_SOURCE -DNETCON_INTERCEPT -LIB_NAME = intercept -SHLIB_EXT=dylib -SHLIB_MAJOR = 1 -SHLIB_MINOR = 8 -COMMON = common -OBJS= netcon/intercept.o -SHLIB = ${LIB_NAME}.${SHLIB_EXT}.${SHLIB_MAJOR}.${SHLIB_MINOR} -SHLDFLAGS = -g -O2 -Wall -I. -nostdlib -shared -LIBS = -ldl -lc -lrt -lpthread - -lib: - ${SHCC} $(intercept_CFLAGS) -I. netcon/intercept.c -o netcon/intercept.o - ${SHCC} $(intercept_CFLAGS) -I. netcon/common.c -o netcon/common.o - ${SHCC} $(intercept_CFLAGS) -I. netcon/sendfd.c -o netcon/sendfd.o - ${SHCC} $(SHLDFLAGS) netcon/intercept.o netcon/common.o netcon/sendfd.o -o netcon/libintercept.so.1.0 $(LIBS) - -install: - cp netcon/libintercept.so.1.0 /lib/libintercept.so.1.0 - ln -sf /lib/libintercept.so.1.0 /lib/libintercept - /usr/bin/install -c netcon/intercept /usr/bin - -uninstall: - rm -r /lib/libintercept.so.1.0 - rm -r /lib/libintercept - rm -r /usr/bin/intercept diff --git a/netcon/NetconEthernetTap.cpp b/netcon/NetconEthernetTap.cpp index 276d481a8..53dfe3f03 100644 --- a/netcon/NetconEthernetTap.cpp +++ b/netcon/NetconEthernetTap.cpp @@ -446,21 +446,29 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns * Send a return value to the client for an RPC */ int NetconEthernetTap::send_return_value(TcpConnection *conn, int retval, int _errno = 0) +{ + if(conn) { + int n = send_return_value(_phy.getDescriptor(conn->rpcSock), retval, _errno); + if(n > 0) + conn->pending = false; + else { + fprintf(stderr, "Unable to send return value to the intercept. Closing connection\n"); + closeConnection(conn); + } + return n; + } + return -1; +} + +int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0) { int sz = sizeof(char) + sizeof(retval) + sizeof(errno); - char retmsg[sz]; - memset(&retmsg, '\0', sizeof(retmsg)); - retmsg[0]=RPC_RETVAL; + char retmsg[sz]; + memset(&retmsg, '\0', sizeof(retmsg)); + retmsg[0]=RPC_RETVAL; memcpy(&retmsg[1], &retval, sizeof(retval)); memcpy(&retmsg[1]+sizeof(retval), &_errno, sizeof(_errno)); - int n = write(_phy.getDescriptor(conn->rpcSock), &retmsg, sz); - if(n > 0) - conn->pending = false; - else { - fprintf(stderr, "Unable to send return value to the intercept. Closing connection\n"); - closeConnection(conn); - } - return n; + return write(fd, &retmsg, sz); } /*------------------------------------------------------------------------------ @@ -484,6 +492,24 @@ int NetconEthernetTap::send_return_value(TcpConnection *conn, int retval, int _e * @param newly allocated PCB * @param error code * @return ERR_OK if everything is ok, -1 otherwise + + [ ] EAGAIN or EWOULDBLOCK - The socket is marked nonblocking and no connections are present + to be accepted. POSIX.1-2001 allows either error to be returned for + 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. + [ ] 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. + [ ] EPROTO - Protocol error. + * */ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err) @@ -507,11 +533,10 @@ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err) int send_fd = tap->_phy.getDescriptor(conn->rpcSock); - int n = write(larg_fd, "z", 1); + int n = write(larg_fd, "z", 1); // accept() in library waits for this byte if(n > 0) { if(sock_fd_write(send_fd, fds[1]) > 0) { new_tcp_conn->pending = true; - fprintf(stderr, "nc_accept(): socketpair = { our=%d, their=%d}\n", fds[0], fds[1]); } else { fprintf(stderr, "nc_accept(%d): unable to send fd to client\n", larg_fd); @@ -526,7 +551,7 @@ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err) tap->lwipstack->_tcp_err(newpcb, nc_err); tap->lwipstack->_tcp_sent(newpcb, nc_sent); tap->lwipstack->_tcp_poll(newpcb, nc_poll, 0.5); - tcp_accepted(conn->pcb); + tcp_accepted(conn->pcb); // Let lwIP know that it can queue additional incoming connections return ERR_OK; } else { @@ -691,8 +716,6 @@ err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err * @param structure containing the data and parameters for this client's RPC * - TODO: set errno appropriately - [ ] EACCES - The address is protected, and the user is not the superuser. [X] EADDRINUSE - The given address is already in use. [X] EBADF - sockfd is not a valid descriptor. @@ -718,7 +741,6 @@ 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); if(conn) { @@ -738,14 +760,18 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st send_return_value(conn, -1, ENOMEM); } else { - send_return_value(conn, ERR_OK, 0); // OK + send_return_value(conn, ERR_OK, ERR_OK); // Success } } - else fprintf(stderr, "handle_bind(): PCB not in CLOSED state. Ignoring BIND request.\n"); - send_return_value(conn, -1, EINVAL); + else { + fprintf(stderr, "handle_bind(): PCB not in CLOSED state. Ignoring BIND request.\n"); + send_return_value(conn, -1, EINVAL); + } } - else fprintf(stderr, "handle_bind(): can't locate connection for PCB\n"); - send_return_value(conn, -1, EBADF); + else { + fprintf(stderr, "handle_bind(): can't locate connection for PCB\n"); + send_return_value(conn, -1, EBADF); // FIXME: This makes no sense + } } /* @@ -754,6 +780,12 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st * @param Client that is making the RPC * @param structure containing the data and parameters for this client's RPC * + + [ ] EADDRINUSE - Another socket is already listening on the same port. + [X] EBADF - The argument sockfd is not a valid descriptor. + [ ] ENOTSOCK - The argument sockfd is not a socket. + [ ] EOPNOTSUPP - The socket is not of a type that supports the listen() operation. + */ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct listen_st *listen_rpc) { @@ -771,13 +803,16 @@ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct liste /* we need to wait for the client to send us the fd allocated on their end for this listening socket */ conn->pending = true; + send_return_value(conn, ERR_OK, ERR_OK); } else { fprintf(stderr, "handle_listen(): unable to allocate memory for new listening PCB\n"); + send_return_value(conn, -1, ENOMEM); // FIXME: This does not have an equivalent errno value } } else { fprintf(stderr, "handle_listen(): can't locate connection for PCB\n"); + send_return_value(conn, -1, EBADF); } } @@ -838,13 +873,16 @@ void NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socke new_conn->their_fd = fds[1]; tcp_connections.push_back(new_conn); sock_fd_write(_phy.getDescriptor(sock), fds[1]); - //fprintf(stderr, "handle_socket(): socketpair = { our=%d, their=%d}\n", fds[0], fds[1]); - /* Once the client tells us what its fd is for the other end, - we can then complete the mapping */ + // Once the client tells us what its fd is for the other end, we can then complete the mapping new_conn->pending = true; } else { + int rpc_fd = _phy.getDescriptor(sock); + sock_fd_write(rpc_fd, -1); // Send a bad fd, to signal error fprintf(stderr, "handle_socket(): Memory not available for new PCB\n"); + if(send_return_value(rpc_fd, -1, ENOMEM) < 0) { + fprintf(stderr, "handle_socket(): Unable to send return value\n"); + } } } diff --git a/netcon/NetconEthernetTap.hpp b/netcon/NetconEthernetTap.hpp index 978c44970..6bf2596e0 100644 --- a/netcon/NetconEthernetTap.hpp +++ b/netcon/NetconEthernetTap.hpp @@ -112,6 +112,7 @@ private: void handle_write(TcpConnection *conn); int send_return_value(TcpConnection *conn, int retval, int _errno); + int send_return_value(int fd, int retval, int _errno); void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *from,void *data,unsigned long len); void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success); diff --git a/netcon/intercept.c b/netcon/intercept.c index b3e919059..df2dc7cfc 100755 --- a/netcon/intercept.c +++ b/netcon/intercept.c @@ -121,6 +121,8 @@ it conflicts with our overriden symbols for read/write */ #define BUF_SZ 1024 #define SERVICE_CONNECT_ATTEMPTS 30 +#define ERR_OK 0 + ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd); /* threading */ @@ -535,20 +537,30 @@ int socket(SOCKET_SIG) ssize_t size = sock_fd_read(fdret_sock, gmybuf, sizeof(gmybuf), &newfd); if(size > 0) { - dwr("socket(): RXed FD = %d\n", newfd); /* send our local-fd number back to service so it can complete its mapping table entry */ memset(cmd, '\0', BUF_SZ); cmd[0] = RPC_FD_MAP_COMPLETION; memcpy(&cmd[1], &newfd, sizeof(newfd)); - write(fdret_sock, cmd, BUF_SZ); - pthread_mutex_unlock(&lock); - return newfd; + if(newfd > -1) { + int n_write = write(fdret_sock, cmd, BUF_SZ); + if(n_write < 0) { + dwr("Error writing perceived FD to service.\n"); + return get_retval(); + } + pthread_mutex_unlock(&lock); + errno = ERR_OK; + return newfd; + } + else { // Try to read retval+errno since we RXed a bad fd + dwr("Error, service sent bad fd.\n"); + return get_retval(); + } } else { dwr("Error while receiving new FD.\n"); pthread_mutex_unlock(&lock); - return -1; + return get_retval(); } return realsocket(socket_family, socket_type, protocol); #endif @@ -704,7 +716,7 @@ int bind(BIND_SIG) pthread_mutex_lock(&lock); write(fdret_sock, cmd, BUF_SZ); pthread_mutex_unlock(&lock); - + errno = ERR_OK; return get_retval(); #endif } @@ -769,24 +781,31 @@ int accept(ACCEPT_SIG) ssize_t size = sock_fd_read(fdret_sock, gmybuf, sizeof(gmybuf), &new_conn_socket); if(size > 0) { - dwr("accept(): RXed FD = %d\n", new_conn_socket); /* Send our local-fd number back to service so it can complete its mapping table */ memset(cmd, '\0', BUF_SZ); cmd[0] = RPC_FD_MAP_COMPLETION; memcpy(&cmd[1], &new_conn_socket, sizeof(new_conn_socket)); pthread_mutex_lock(&lock); - write(fdret_sock, cmd, BUF_SZ); + 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"); + errno = ECONNABORTED; + return -1; + } pthread_mutex_unlock(&lock); - return new_conn_socket; + errno = ERR_OK; + return new_conn_socket; // OK } else { - dwr("Error while receiving new FD.\n"); + dwr("Error receiving new FD from service. Service might be down.\n"); + errno = ECONNABORTED; return -1; } } - errno = EWOULDBLOCK; + dwr("Error reading signal byte from service. Service might be down.\n"); + //errno = EWOULDBLOCK; + errno = ECONNABORTED; return -1; - /* TODO/FIXME: Set errno */ #endif } @@ -822,9 +841,7 @@ int listen(LISTEN_SIG) pthread_mutex_lock(&lock); write(fdret_sock,cmd, BUF_SZ); pthread_mutex_unlock(&lock); - - return 0; - /* FIXME: get real return value (should be 0 / -1) */ - /* FIXME: Also set errno */ + errno = ERR_OK; + return get_retval(); #endif } diff --git a/netcon/libintercept.so.1.0 b/netcon/libintercept.so.1.0 index f4034ee29..e50a40c21 100755 Binary files a/netcon/libintercept.so.1.0 and b/netcon/libintercept.so.1.0 differ