kprobe

connect()

Table of Contents

The connect() system call is a crucial function in Linux that enables processes to establish connections between sockets. By initiating a connection request to a remote host, connect() plays a pivotal role in network communication, allowing programs to connect and exchange data over various types of connections, such as TCP/IP. Understanding the connect() system call is essential for building networked applications and leveraging the power of networking in Linux environments.

       #include <sys/socket.h>

       int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);

Prerequiste definiton

The connect() system call connects the socket referred to by the file descriptor sockfd to the address specified by addr.The addrlen argument specifies the size of addr. The format of the address in addr is determined by the address space of the socket sockfd; see socket(2) and address_families for further details.

The definition for connect can be founde here.

SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, int, addrlen)
{
    return __sys_connect(fd, uservaddr, addrlen);
}

Let’s break down the code:

This code defines the connect system call with three arguments: fduservaddr, and addrlen.

Here’s what each argument represents:

  • int fd: The file descriptor of the socket to connect.
  • struct sockaddr __user *uservaddr: A pointer to the sockaddr structure that holds the address to which the socket should connect. The __user attribute is typically used in the kernel to denote a user-space memory pointer.
  • int addrlen: The length of the sockaddr structure.

The SYSCALL_DEFINE3 macro expands to the actual definition of the system call, which includes the function body. In this case, the body simply calls the __sys_connect function and returns its result.

int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
{
	int ret = -EBADF;
	struct fd f;

	f = fdget(fd);
	if (f.file) {
		struct sockaddr_storage address;

		ret = move_addr_to_kernel(uservaddr, addrlen, &address);
		if (!ret)
			ret = __sys_connect_file(f.file, &address, addrlen, 0);
		fdput(f);
	}

	return ret;
}

This function is responsible for connecting a socket to the specified address.

Implementation of the __sys_connect function, which is called by the connect() system call. This function is responsible for connecting a socket to the specified address.

Let’s break down the code:

int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
{
    int ret = -EBADF;
    struct fd f;
    
    f = fdget(fd);
    if (f.file) {
        struct sockaddr_storage address;
        
        ret = move_addr_to_kernel(uservaddr, addrlen, &address);
        if (!ret)
            ret = __sys_connect_file(f.file, &address, addrlen, 0);
        fdput(f);
    }
    
    return ret;
}

Here’s an explanation of the code:

  1. The function __sys_connect takes three arguments: fd (the file descriptor of the socket to connect)uservaddr (a pointer to the user-space sockaddr structure containing the address to connect to), and addrlen (the length of the sockaddr structure).

  2. The variable ret is initialized with the value -EBADF, which stands for “bad file descriptor.” This is used as a default return value in case the file descriptor is invalid.

  3. The function fdget is called with the file descriptor fd to get a file structure associated with the file descriptor. This function performs various operations to obtain a reference to the file structure.

  4. If f.file (the file structure) is not null (i.e., a valid file structure is obtained), the function continues with the connection process. Otherwise, the default return value -EBADF is returned.

  5. The function move_addr_to_kernel is called to move the user-space sockaddr structure (uservaddr) to kernel space. This function ensures that the address structure is safely accessible in the kernel. The moved address is stored in the address variable of type struct sockaddr_storage.

  6. If move_addr_to_kernel succeeds (returns 0), the function __sys_connect_file is called with the file structure, the address in kernel space (&address), the addrlen, and a flags parameter set to 0. This function performs the actual socket connection using the provided parameters.

  7. After the connection is attempted, the function fdput is called to release the file structure reference obtained by fdget.

  8. Finally, the return value (ret) is returned, which represents the result of the connection attempt. It will be either a negative error code (e.g., -EBADF if the file descriptor is invalid) or a non-negative value indicating success.

Description

If the socket sockfd is of type SOCK_DGRAM, then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received. If the socket is of type SOCK_STREAM or SOCK_SEQPACKET, this call attempts to make a connection to the socket that is bound to the address specified by addr.

Some protocol sockets (e.g., UNIX domain stream sockets) may successfully connect() only once.

Some protocol sockets (e.g., datagram sockets in the UNIX and Internet domains) may use connect() multiple times to change their association.

Some protocol sockets (e.g., TCP sockets as well as datagram sockets in the UNIX and Internet domains) may dissolve the association by connecting to an address with the sa_family member of sockaddr set to AF_UNSPEC; thereafter, the socket can be connected to another address. (AF_UNSPEC is supported on Linux since kernel 2.2.)

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top