Browse Source

getsockname() implemented

Joseph Henry 9 years ago
parent
commit
a730c86907
4 changed files with 90 additions and 7 deletions
  1. 32 2
      netcon/Intercept.c
  2. 9 0
      netcon/Intercept.h
  3. 45 5
      netcon/NetconEthernetTap.cpp
  4. 4 0
      netcon/NetconEthernetTap.hpp

+ 32 - 2
netcon/Intercept.c

@@ -691,6 +691,7 @@ int bind(BIND_SIG)
   memcpy(&cmd[1], &rpc_st, sizeof(struct bind_st));
   pthread_mutex_lock(&lock);
   send_command(fdret_sock, cmd);
+
   err = get_retval();
   pthread_mutex_unlock(&lock);
   errno = ERR_OK;
@@ -1022,6 +1023,7 @@ int dup3(DUP3_SIG)
 -------------------------------------- getsockname()----------------------------
 ------------------------------------------------------------------------------*/
 
+/* define GETSOCKNAME_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen */
 int getsockname(GETSOCKNAME_SIG)
 {
   if (realgetsockname == NULL) {
@@ -1029,9 +1031,37 @@ int getsockname(GETSOCKNAME_SIG)
     return -1;
   }
 
-  // TODO
+  char cmd[BUF_SZ];
+  struct getsockname_st rpc_st;
+  rpc_st.sockfd = sockfd;
+  memcpy(&rpc_st.addr, addr, sizeof(struct sockaddr));
+  memcpy(&rpc_st.addrlen, &addrlen, sizeof(socklen_t));
+  cmd[0] = RPC_GETSOCKNAME;
+  memcpy(&cmd[1], &rpc_st, sizeof(struct getsockname_st));
+  pthread_mutex_lock(&lock);
+  send_command(fdret_sock, cmd);
+  pthread_mutex_unlock(&lock);
+
+  char addrbuf[sizeof(struct sockaddr)];
+  memset(addrbuf, '\0', sizeof(struct sockaddr));
+  read(fdret_sock, &addrbuf, sizeof(struct sockaddr)); // read address from service
+  memcpy(addr, addrbuf, sizeof(struct sockaddr)); 
+  *addrlen = 16;
+
+  struct sockaddr_in *connaddr;
+  connaddr = (struct sockaddr_in *) &addr;
 
-  return realgetsockname(sockfd,addr,addrlen);
+  int ip = connaddr->sin_addr.s_addr;
+  unsigned char d[4];
+  d[0] = ip & 0xFF;
+  d[1] = (ip >>  8) & 0xFF;
+  d[2] = (ip >> 16) & 0xFF;
+  d[3] = (ip >> 24) & 0xFF;
+
+  int port = connaddr->sin_port;
+  dwr(MSG_ERROR, " handle_getsockname(): returning address: %d.%d.%d.%d: %d\n", d[0],d[1],d[2],d[3], port);
+
+  return 0;
 }
 
 /*------------------------------------------------------------------------------

+ 9 - 0
netcon/Intercept.h

@@ -56,6 +56,7 @@
 #define RPC_LISTEN			 		10
 #define RPC_SOCKET			 		11
 #define RPC_SHUTDOWN		 		12
+#define RPC_GETSOCKNAME				13
 
 /* Administration RPC codes */
 #define RPC_MAP						20	/* Give the service the value we "see" for the new buffer fd */
@@ -175,6 +176,14 @@ struct shutdown_st
 	int how;
 };
 
+struct getsockname_st
+{
+	int sockfd;
+	struct sockaddr addr;
+	socklen_t addrlen;
+};
+
+
 #define CONNECT_SOCKARG struct sockaddr *
 #define SELECT_SIG int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout
 #define IOCTL_SIG int __fd, unsigned long int __request, ...

+ 45 - 5
netcon/NetconEthernetTap.cpp

@@ -149,6 +149,8 @@ public:
   PhySocket *dataSock;
   struct tcp_pcb *pcb;
 
+  struct sockaddr_in *addr;
+
   unsigned char buf[DEFAULT_READ_BUFFER_SIZE];
   int idx;
 };
@@ -715,7 +717,7 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
 	    memcpy(&bind_rpc,  &buf[IDX_PAYLOAD+1], sizeof(struct bind_st));
 	    handle_bind(sock, uptr, &bind_rpc);
 			break;
-  	case RPC_CONNECT:
+  	  case RPC_CONNECT:
 			dwr(MSG_DEBUG, "RPC_CONNECT\n");
 	    struct connect_st connect_rpc;
 	    memcpy(&connect_rpc,  &buf[IDX_PAYLOAD+1], sizeof(struct connect_st));
@@ -727,11 +729,17 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
 	    	memcpy(&newfd, &buf[IDX_PAYLOAD+1], sizeof(int));
 	    	handle_retval(sock, uptr, rpc_count, newfd);
 			break;
-		case RPC_MAP_REQ:
+	  case RPC_MAP_REQ:
 			dwr(MSG_DEBUG, "RPC_MAP_REQ\n");
 			handle_map_request(sock, uptr, buf);
 			break;
-		default:
+	  case RPC_GETSOCKNAME:
+	  		dwr(MSG_DEBUG, "RPC_GETSOCKNAME\n");
+	  		struct getsockname_st getsockname_rpc;
+	    	memcpy(&getsockname_rpc,  &buf[IDX_PAYLOAD+1], sizeof(struct getsockname_st));
+	  		handle_getsockname(sock, uptr, &getsockname_rpc);
+	  		break;
+	  default:
 			break;
 	}
 }
@@ -1166,6 +1174,35 @@ void NetconEthernetTap::handle_retval(PhySocket *sock, void **uptr, int rpc_coun
 	}
 }
 
+
+/* Return the address that the socket is bound to */
+void NetconEthernetTap::handle_getsockname(PhySocket *sock, void **uptr, struct getsockname_st *getsockname_rpc)
+{
+	TcpConnection *conn = getConnectionByTheirFD(sock, getsockname_rpc->sockfd);
+	dwr(MSG_DEBUG, "handle_getsockname(): sockfd = %d\n", getsockname_rpc->sockfd);
+
+	/*
+	int ip = conn->addr->sin_addr.s_addr;
+	unsigned char d[4];
+	d[0] = ip & 0xFF;
+	d[1] = (ip >>  8) & 0xFF;
+	d[2] = (ip >> 16) & 0xFF;
+	d[3] = (ip >> 24) & 0xFF;
+	int port = conn->addr->sin_port;
+	dwr(MSG_ERROR, " handle_getsockname(): returning address: %d.%d.%d.%d: %d\n", d[0],d[1],d[2],d[3], port);
+	*/
+	
+	// Assemble address "command" to send to intercept
+	char retmsg[sizeof(struct sockaddr)];
+	memset(&retmsg, '\0', sizeof(retmsg));
+	dwr(MSG_ERROR, " handle_getsockname(): %d\n", sizeof(retmsg));
+	memcpy(&retmsg, conn->addr, sizeof(struct sockaddr));
+
+	// Get connection's RPC fd and send structure containing bound address
+	int fd = _phy.getDescriptor(conn->rpcSock);
+	write(fd, &retmsg, sizeof(struct sockaddr));
+}
+
 /*
  * Handles an RPC to bind an LWIP PCB to a given address and port
  *
@@ -1207,8 +1244,8 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
   connaddr = (struct sockaddr_in *) &bind_rpc->addr;
   int conn_port = lwipstack->ntohs(connaddr->sin_port);
   ip_addr_t conn_addr;
-	conn_addr.addr = *((u32_t *)_ips[0].rawIpData());
-	TcpConnection *conn = getConnectionByTheirFD(sock, bind_rpc->sockfd);
+  conn_addr.addr = *((u32_t *)_ips[0].rawIpData());
+  TcpConnection *conn = getConnectionByTheirFD(sock, bind_rpc->sockfd);
 
   dwr(MSG_DEBUG, " handle_bind(%d)\n", bind_rpc->sockfd);
 
@@ -1233,7 +1270,10 @@ void NetconEthernetTap::handle_bind(PhySocket *sock, void **uptr, struct bind_st
 					send_return_value(conn, -1, ENOMEM); // FIXME: Closest match
 			}
 			else
+			{
+				conn->addr = (struct sockaddr_in *) &bind_rpc->addr;
 				send_return_value(conn, ERR_OK, ERR_OK); // Success
+			}
     }
     else {
 			dwr(MSG_ERROR, " handle_bind(): PCB (%x) not in CLOSED state. Ignoring BIND request.\n", conn->pcb);

+ 4 - 0
netcon/NetconEthernetTap.hpp

@@ -49,6 +49,9 @@ struct socket_st;
 struct listen_st;
 struct bind_st;
 struct connect_st;
+struct getsockname_st;
+struct accept_st;
+
 
 namespace ZeroTier {
 
@@ -109,6 +112,7 @@ private:
 	// RPC handlers (from NetconIntercept)
 	void unload_rpc(void *data, pid_t &pid, pid_t &tid, int &rpc_count, char (timestamp[20]), char &cmd, void* &payload);
 
+	void handle_getsockname(PhySocket *sock, void **uptr, struct getsockname_st *getsockname_rpc);
 	void handle_bind(PhySocket *sock, void **uptr, struct bind_st *bind_rpc);
 	void handle_listen(PhySocket *sock, void **uptr, struct listen_st *listen_rpc);
 	void handle_map_request(PhySocket *sock, void **uptr, unsigned char* buf);