Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where's glibc's socket implementation at?

In glibc 2.22, in the /socket directory, the socket library implementation is located.
When opening any of these files, though, all I see is an error-setting function with some macros beneath it.
Here's an example file (/socket/send.c):

#include <errno.h>
#include <sys/socket.h>

/* Send N bytes of BUF to socket FD.  Returns the number sent or -1.  */
ssize_t
__send (fd, buf, n, flags)
     int fd;
     const __ptr_t buf;
     size_t n;
     int flags;
{
  __set_errno (ENOSYS);
  return -1;
}
libc_hidden_def (__send)
weak_alias (__send, send)

stub_warning (send)

(Comment with license removed.)

Where is that send the weak_alias macro has as an argument? Where are these macros defined?
I think this is due to compatibility with some crappy old compiler but why do they still use K&R syntax?
And most important, why is __send defined like that?

like image 860
cadaniluk Avatar asked Dec 28 '15 23:12

cadaniluk


People also ask

Where are sockets implemented?

Socket are generally employed in client server applications. The server creates a socket, attaches it to a network port addresses then waits for the client to contact it. The client creates a socket and then attempts to connect to the server socket.

How are sockets implemented?

On the Internet, stream sockets are typically implemented using TCP so that applications can run across any networks using TCP/IP protocol. Raw sockets. Allow direct sending and receiving of IP packets without any protocol-specific transport layer formatting.

How is socket implemented in Linux?

Network sockets need support from an underlying protocol such as TCP (Transmission Control Protocol) or the lower-level UDP (User Datagram Protocol). By contrast, IPC sockets rely upon the local system kernel to support communication; in particular, IPC sockets communicate using a local file as a socket address.

What are sockets in programming?

A socket is a communications connection point (endpoint) that you can name and address in a network. Socket programming shows how to use socket APIs to establish communication links between remote and local processes.


2 Answers

There's a couple of things going on here.

First, as explained in this answer, glibc itself cannot define random identifiers that standard C does not reserve, because standard C allows programs to define those identifiers itself. Names beginning with a double underscore are reserved for the implementation, so the implementation here defines the function __send(). The weak alias then allows the name send() to be used to refer to it, but also allows that reference to be overridden by a strong definition somewhere else.

Second, as explained in the glibc documentation, for ease of porting glibc requires any machine-specific function to have a corresponding generic function. If a corresponding generic function can be written, then it should be, but if not, the generic one should be a "stub function", which essentially just sets errno to ENOSYS (not implemented) and returns an error. If there is a machine-specific function provided, that'll be used instead of the stub function. Since send() requires a system call, obviously it cannot be written in a machine-independent way, so there's a stub function for it here. So you should be able to locate a machine-specific implementation (or a variety of them) of __send(), for instance, at /sysdeps/unix/sysv/linux/x86_64/send.c in the glibc source tree.

Incidentally, since send() is indeed a system call, all you're typically going to see in glibc is a short assembly language routine that makes the system call. The code that actually does stuff will live in the kernel.

like image 138
Crowman Avatar answered Sep 27 '22 22:09

Crowman


Generally the socket functions like send, bind, and socket are system calls, which means they are provided by the operating system directly. Notice on a unix system you would type man 2 socket compared to man 3 fopen. The former is a system call and the latter is a library function. So glibc isn't providing any of the functionality here which is why you can't find the implementation in the glibc sources.

As to the __send and the weak_alias, what's going on there is that glibc is creating a weak binding from send to __send which basically means that if you call send and there is no other implementation available, you'll get glibc's __send. This just returns ENOSYS precisely because there is no implementation available. If there is a real implementation, it will override the weak binding.

The sysdeps directory is where all the dirty work is done to wrap systems calls. For example, look at sysdeps/unix/sysv/linux/x86_64/syscalls.list and you'll see the mapping from C function calls to the OS syscalls for that OS and architecture. Look at syscall.S in the same directory and you'll see how the syscalls are actually made. In short, there is no real user-level code implementing syscalls, the libc implementation puts the number associated with the syscall in a register and then executes the syscall instruction. All of the real implementation is in the kernel.

like image 42
Turn Avatar answered Sep 27 '22 23:09

Turn