Search code examples
csocketsposixglibc

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?


Solution

  • 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.