Ejemplo n.º 1
0
int reopen_socket_with_other_family(int s, int family)
{
	int type, protocol, result, saved_fd;

	result = 0;

	// duplicate the file descriptor
	saved_fd = dup(s);

	// record the type, protocol and fd of the existing socket
	type = get_socket_type(s);
	protocol = get_socket_protocol(s);
	
	// close the socket - this way the fd integer should be available for our new socket
	// and the calling program will not notice that the socket is not the same
	original_close(s);

	// create an IPv6 socket on the same file descriptor s
	if (create_socket_on_specified_free_fd(s, family, type, protocol) == -1)
	{	// failed ! recreate file descriptor previously closed
		dup2(saved_fd, s);
		result = -1;
	}
	else
	{
		report_socket_options(saved_fd, s);
	}

	// saved_fd is not useful anymore
	original_close(saved_fd);

	return result;
}
Ejemplo n.º 2
0
/*
	Consider the following scenario:

	// this is what the code of the program does
	... 				// initial state: fd == 0 -> stdin, fd == 1 -> stdout, fd == 2 -> stderr
	1- file = open(...); 		// => file = 3	
	2- s = socket(...IPv4...);	// => s = 4	
	3- close(file);			// => 3 is now free
	4- connect(s, ...) ... 		// this connect() call will call the IPv6 CARE handler:
		// this part is handled by IPv6 CARE 
		5- result = original_connect(s, ...);	// call of connect() of the libc
		   ... if this first connection attempt fails, IPv6 CARE will want to reopen s as an IPv6 socket:
		7- close(s);				// => 4 is now free 
		8- s = socket(...IPv6...);		// => s = 3, not 4!!! (because of line 3) 
		9- original_connect(s, ...);		// try to connect with the IPv6 socket
		
	In this case the calling program would be confused by the behavior of IPv6 CARE
	because the socket's fd would not be the same. 
	
	A correct code in order to reopen the socket on fd 4 would be, instead of line 7 and 8:
		close(s);               	// => 4 is now free 
		dummy_s = socket(...IPv6...); 	// => dummy_s = 3
		s = socket(...IPv6...); 	// => s = 4, ok
		close(dummy_s);	
	
	That's basically what the following code does. 
*/
int create_socket_on_specified_free_fd(int fd, int family, int socktype, int protocol)
{
	int result, new_socket;

	result = -1;

	debug_print(1, "Trying to create socket on fd = %d.\n", fd);

	// create the socket
	new_socket = original_socket(family, socktype, protocol);

	if (new_socket != -1)
	{	// if ok check if the file descriptor is the correct one
		if (new_socket == fd)
		{
			result = 0; // ok
			debug_print(1, "socket creation ok!\n");
		}
		else
		{
			// if not create a copy of the file descriptor
			// with the expected integer ...
			if (dup2(new_socket, fd) != -1)
			{	
				result = 0; // ok
				debug_print(1, "socket creation ok!\n");
			}

			// ... and close the original file descriptor
			original_close(new_socket);
		}
	}
	return result;
}
Ejemplo n.º 3
0
int try_connect_and_register_connection_and_manage_wrong_family(int s, 
				int current_socket_family, struct polymorphic_sockaddr *psa,
                                int *connect_call_result, int *connect_call_errno)
{
	int result = -1;
	int saved_fd;

	// duplicate the file descriptor
	saved_fd = dup(s);

	if (current_socket_family != psa->sockaddr.sa.sa_family)
	{
		if (reopen_socket_with_other_family(s, psa->sockaddr.sa.sa_family) == 0)
		{ 	// try to connect
			result = try_connect_and_register_connection(s, psa, connect_call_result, connect_call_errno);
			if (result == 0)
			{
				debug_print(1, "connection ok!\n");
				register_created_socket(INITIAL_SOCKET_WAS_CLOSED, s);
			}
			else
			{	// reopen socket as initially
				debug_print(1, "connection failed. recreating socket as ipv4.\n");
				original_close(s);
				dup2(saved_fd, s);
			}
		}
		else
		{	// could not recreate the socket as AF_INET6
			debug_print(1, "could not reopen socket as IPv6.\n");
			*connect_call_result = -1;
			*connect_call_errno = EHOSTUNREACH;
		}
	}
	else
	{
		result = try_connect_and_register_connection(s, psa, connect_call_result, connect_call_errno);
	}

	// saved_fd is not useful anymore
	original_close(saved_fd);

	return result;
}
Ejemplo n.º 4
0
int close(int sockfd)
{
	if (sockfd <= 2)
	{
		preeny_info("Disabling close on %d\n", sockfd);
		return 0;
	}
	else
	{
		original_close(sockfd);
	}
}