Browse Source

Refactored connect(), added checks to socket(), updated checklists

Joseph Henry 9 years ago
parent
commit
1fd04557c7
3 changed files with 97 additions and 41 deletions
  1. 41 15
      netcon/NetconEthernetTap.cpp
  2. 56 26
      netcon/intercept.c
  3. BIN
      netcon/libintercept.so.1.0

+ 41 - 15
netcon/NetconEthernetTap.cpp

@@ -503,7 +503,7 @@ int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0)
 	[I] EBADF - The descriptor is invalid.
 	[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).
+	[-] 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).
 	[I] EINVAL - (accept4()) invalid value in flags.
 	[I] EMFILE - The per-process limit of open file descriptors has been reached.
@@ -806,6 +806,12 @@ void NetconEthernetTap::handle_retval(PhySocket *sock, void **uptr, unsigned cha
  * @param structure containing the data and parameters for this client's RPC
  *
 
+ i := should be implemented in intercept lib
+ I := is implemented in intercept lib
+ X := is implemented in service
+ ? := required treatment Unknown
+ - := Not needed
+
 	[ ]	EACCES - The address is protected, and the user is not the superuser.
 	[X]	EADDRINUSE - The given address is already in use.
 	[I]	EBADF - sockfd is not a valid descriptor.
@@ -876,10 +882,16 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
  * @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.
-	[i] ENOTSOCK - The argument sockfd is not a socket.
-	[i] EOPNOTSUPP - The socket is not of a type that supports the listen() operation.
+ i := should be implemented in intercept lib
+ I := is implemented in intercept lib
+ X := is implemented in service
+ ? := required treatment Unknown
+ - := Not needed
+
+[?] EADDRINUSE - Another socket is already listening on the same port.
+[I] EBADF - The argument sockfd is not a valid descriptor.
+[I] ENOTSOCK - The argument sockfd is not a socket.
+[I] 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)
@@ -890,6 +902,10 @@ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct liste
       fprintf(stderr, "handle_listen(): PCB is already in listening state.\n");
       return;
     }
+
+		// TODO: Implement liste_with_backlog
+		// FIXME: Correct return values from this method, most is handled in intercept lib
+
     struct tcp_pcb* listening_pcb = lwipstack->tcp_listen(conn->pcb);
     if(listening_pcb != NULL) {
       conn->pcb = listening_pcb;
@@ -924,13 +940,17 @@ void NetconEthernetTap::handle_listen(PhySocket *sock, void **uptr, struct liste
  * @param structure containing the data and parameters for this client's RPC
  *
 
-	TODO: set errno appropriately
+ i := should be implemented in intercept lib
+ I := is implemented in intercept lib
+ X := is implemented in service
+ ? := required treatment Unknown
+ - := Not needed
 
 	[-] 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.
-  [i] EMFILE - Process file table overflow.
+  [I] EAFNOSUPPORT - The implementation does not support the specified address family.
+  [I] EINVAL - Unknown protocol, or protocol family not available.
+  [I] EINVAL - Invalid flags in type.
+  [I] EMFILE - Process file table overflow.
   [i] ENFILE - The system limit on the total number of open files has been reached.
   [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.
@@ -974,23 +994,29 @@ void NetconEthernetTap::handle_socket(PhySocket *sock, void **uptr, struct socke
  * @param PhySocket associated with this RPC connection
  * @param structure containing the data and parameters for this client's RPC
 
-	--- Error handling in this method will only catch problems which are immeidately
+	--- Error handling in this method will only catch problems which are immedately
 	    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 ...
+	 i := should be implemented in intercept lib
+ 	 I := is implemented in intercept lib
+ 	 X := is implemented in service
+ 	 ? := required treatment Unknown
+ 	 - := Not needed
+
+	[-] 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.
+	[I] 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.
+	[-] 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.
+	[I] ENOTSOCK - The file descriptor is not associated with a socket.
 	[X] ETIMEDOUT - Timeout while attempting connection.
 
  *

+ 56 - 26
netcon/intercept.c

@@ -528,6 +528,16 @@ int socket(SOCKET_SIG)
     return -EAFNOSUPPORT;
   if (socket_type < 0 || socket_type >= SOCK_MAX)
     return -EINVAL;
+  /* Check that we haven't hit the soft-limit file descriptors allowed */
+  /* FIXME: Find number of open fds
+  struct rlimit rl;
+  getrlimit(RLIMIT_NOFILE, &rl);
+  if(sockfd >= rl.rlim_cur){
+    errno = EMFILE;
+    return -1;
+  }
+  */
+  /* FIXME: detect ENFILE condition */
 #endif
 
 #ifdef DUMMY
@@ -597,8 +607,21 @@ int socket(SOCKET_SIG)
    connect() intercept function */
 int connect(CONNECT_SIG)
 {
-  int err;
+#ifdef CHECKS
+  /* Check that this is a valid fd */
+  if(fcntl(__fd, F_GETFD) < 0) {
+    return -1;
+    errno = EBADF;
+  }
+  /* Check that it is a socket */
+  int sock_type;
+  socklen_t sock_type_len = sizeof(sock_type);
+  if(getsockopt(__fd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
+    errno = ENOTSOCK;
+    return -1;
+  }
   /* FIXME: Check that address is in user space, return EFAULT ? */
+#endif
 
 #ifdef DUMMY
   dwr("connect(%d)\n", __fd);
@@ -606,16 +629,17 @@ int connect(CONNECT_SIG)
 
 #else
   /* make sure we don't touch any standard outputs */
-  if(__fd == STDIN_FILENO || __fd == STDOUT_FILENO || __fd == STDERR_FILENO)
+  if(__fd == STDIN_FILENO || __fd == STDOUT_FILENO || __fd == STDERR_FILENO){
+    if (realconnect == NULL) {
+      dwr("Unresolved symbol: connect(). Library is exiting.\n");
+      exit(-1);
+    }
     return(realconnect(__fd, __addr, __len));
-  int sock_type = -1;
-  socklen_t sock_type_len = sizeof(sock_type);
+  }
+
   struct sockaddr_in *connaddr;
 	connaddr = (struct sockaddr_in *) __addr;
 
-  getsockopt(__fd, SOL_SOCKET, SO_TYPE,
-		   (void *) &sock_type, &sock_type_len);
-
   if(__addr != NULL && (connaddr->sin_family == AF_LOCAL
     || connaddr->sin_family == PF_NETLINK
     || connaddr->sin_family == AF_NETLINK
@@ -624,13 +648,9 @@ int connect(CONNECT_SIG)
     return err;
   }
 
-  char cmd[BUF_SZ];
-  if (realconnect == NULL) {
-    dwr("Unresolved symbol: connect()\n");
-    return -1;
-  }
-
   /* assemble and route command */
+  int err;
+  char cmd[BUF_SZ];
   memset(cmd, '\0', BUF_SZ);
   struct connect_st rpc_st;
   rpc_st.__tid = syscall(SYS_gettid);
@@ -778,7 +798,6 @@ int accept(ACCEPT_SIG)
 #ifdef CHECKS
   /* Check that this is a valid fd */
   if(fcntl(sockfd, F_GETFD) < 0) {
-    dwr("EBADF\n");
     return -1;
     errno = EBADF;
   }
@@ -787,13 +806,11 @@ int accept(ACCEPT_SIG)
   socklen_t sock_type_len = sizeof(sock_type);
   if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
     errno = ENOTSOCK;
-    dwr("ENOTSOCK\n");
     return -1;
   }
   /* Check that this socket supports accept() */
   if(!(sock_type && (SOCK_STREAM | SOCK_SEQPACKET))) {
     errno = EOPNOTSUPP;
-    dwr("EOPNOTSUPP\n");
     return -1;
   }
   /* Check that we haven't hit the soft-limit file descriptors allowed */
@@ -801,7 +818,6 @@ int accept(ACCEPT_SIG)
   getrlimit(RLIMIT_NOFILE, &rl);
   if(sockfd >= rl.rlim_cur){
     errno = EMFILE;
-    dwr("EMFILE\n");
     return -1;
   }
 #endif
@@ -822,16 +838,12 @@ int accept(ACCEPT_SIG)
     return -1;
   }
 
-  char gmybuf[16];
-  int new_conn_socket;
-
-  char c[1];
-  int n = read(sockfd, c, sizeof(c));
+  char gmybuf[16], c[1];
+  int new_conn_socket, n = read(sockfd, c, sizeof(c));
   if(n > 0)
   {
     ssize_t size = sock_fd_read(fdret_sock, gmybuf, sizeof(gmybuf), &new_conn_socket);
-    if(size > 0)
-    {
+    if(size > 0) {
       /* 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;
@@ -869,9 +881,27 @@ int accept(ACCEPT_SIG)
    listen() intercept function */
 int listen(LISTEN_SIG)
 {
+  #ifdef CHECKS
+  /* Check that this is a valid fd */
+  if(fcntl(sockfd, F_GETFD) < 0) {
+    return -1;
+    errno = EBADF;
+  }
+  /* Check that it is a socket */
+  int sock_type;
+  socklen_t sock_type_len = sizeof(sock_type);
+  if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
+    errno = ENOTSOCK;
+    return -1;
+  }
+  /* Check that this socket supports accept() */
+  if(!(sock_type && (SOCK_STREAM | SOCK_SEQPACKET))) {
+    errno = EOPNOTSUPP;
+    return -1;
+  }
+  #endif
+
   int err;
-  /* FIXME: Check that this socket supports listen(), return EOPNOTSUPP */
-  /* FIXME: Check that the provided fd is a socket, return ENOTSOCK */
 
 #ifdef DUMMY
     dwr("listen(%d)\n", sockfd);

BIN
netcon/libintercept.so.1.0