givesocket() — Make the specified socket available

Standards

Standards / Extensions C or C++ Dependencies
z/OS® UNIX both  

Format

#define _OPEN_SYS_SOCK_EXT
#include <sys/socket.h>

int givesocket(int d, struct clientid *clientid);

General description

The givesocket() call makes the specified socket available to a takesocket() call issued by another program. Any socket can be given. Typically, givesocket() is used by a master program that obtains sockets by means of accept() and gives them to application programs that handle one socket at a time.
Parameter
Description
d
The descriptor of a socket to be given to another application.
clientid
A pointer to a client ID structure specifying the program to which the socket is to be given.

To pass a socket, the giving program first calls givesocket() with the client ID structure filled in as follows:

The clientid structure:
      struct clientid {
         int domain;
         union  {
           char name[8];
           struct {
             int NameUpper;
             pid_t pid;
           } c_pid;
         } c_name;
         char subtaskname[8];

         struct  {
           char type;
           union  {
              char specific[19];
              struct  {
                char unused[3];
                int SockToken;
              } c_close;
           } c_func;
         } c_reserved;
      };
Element
Description
domain
The domain of the input socket descriptor.
c_name.name
If the clientid was set by a getclientid() call, c_name.name can be
  • set to the application program's address space name, left-justified and padded with blanks. The application program can run in the same address space as the master program, in which case this field is set to the master program's address space.
  • set to blanks, so any z/OS address space can take the socket.
subtaskname
If the clientid was set by a getclientid() call, subtaskname can be
  • set to the task identifier of the taker. This, combined with a c_name.name value, allows only a process with this c_name.name and subtaskname to take the socket.
  • set to blanks. If c_name.name has a value and subtaskname is blank, any task with that c_name.name can take the socket.
c_pid.pid
If the clientid was set by a __getclientid() call, c_pid.pid should be set to the process id (PID) of the taker, so only a process with that PID can take the socket. The subtaskname field is ignored when the c_pid has a value.
c_reserved.type

When set to SO_CLOSE, this indicates the socket should be automatically closed by givesocket(), and a unique socket identifying token is to be returned in c_close.SockToken. The c_close.SockToken should be passed to the taking program to be used as input to takesocket() instead of the socket descriptor. The now closed socket descriptor could be re-used by the time the takesocket() is called, so the c_close.SockToken should be used for takesocket().

When set to _SO_SELECT, this indicates that the application intends to block on the select() for exception, waiting for the takesocket() to occur before closing the socket. If c_reserved.type is set to _SO_SELECT and the caller of givesocket() closes the socket before it has been taken, the connection will be severed. _SO_SELECT also allows select() to return exception status if select() is done after the socket was taken with takesocket().

When set to zero, this indicates that the application will not be calling select() to coordinate with the taker of the socket. Either the socket is not going to be closed or the giver and taker have some other method of coordination for the giver to know when the taker has called takesocket(). Note that if select() for exception is called before takesocket(), the select will return when takesocket() is called but if select() is called after takesocket(), it will hang. _SO_SELECT should be used if select() is going to be called by the giver.

Also, if the given socket is closed before the takesocket() is issued, it is possible for that socket descriptor number to be reused in the giver's process. A sequence of accept(), givesocket(), and close() calls issued several times before any takesocket() calls can result in several sockets with the same descriptor number waiting to be taken. In this case, the oldest given socket will be taken; that is, in FIFO order. Note that if select() is called when there are several given sockets with the same descriptor number waiting to be taken, select() will operate on the current active socket for that descriptor. It effectively waits for the last (newest) given socket to be taken; that is, in LIFO order.

c_close.SockToken
The unique socket identifying token returned by givesocket() to be used as input to takesocket(), instead of the socket descriptor when c_reserved.type has been set to SO_CLOSE.
c_reserved
Specifies binary zeros if an automatic close of a socket is not to be done by givesocket().
Using name and subtaskname for givesocket/takesocket:
  1. The giving program calls getclientid() to obtain its client ID. The giving program calls givesocket() to make the socket available for a takesocket() call. The giving program passes its client ID along with the descriptor of the socket to be given to the taking program by the taking program's startup parameter list.
  2. The taking program calls takesocket(), specifying the giving program's client ID and socket descriptor.
  3. Waiting for the taking program to take the socket, the giving program uses select() to test the given socket for an exception condition. When select() reports that an exception condition is pending, the giving program calls close() to free the given socket.
  4. If the giving program closes the socket before a pending exception condition is indicated, the connection is immediately reset, and the taking program's call to takesocket() is unsuccessful. Calls other than the close() call issued on a given socket return -1, with errno set to EBADF.
Note: For backward compatibility, a client ID can point to the struct client ID structure obtained when the target program calls getclientid(). In this case, only the target program, and no other programs in the target program's address space, can take the socket.
Using process id (PID) for givesocket/takesocket:
  1. The giving program calls __getclientid() to obtain its client ID. The giving program sets the c_pid.pid in the clientid structure to the PID of the taking program that will take the socket (that is, issue the takesocket() call). This ensures only a process that has obtained the giver's PID can take the specified socket. If the giving program wants the socket to be automatically closed by givesocket(), c_reserved.type should be set to SO_CLOSE. The giving program calls givesocket() to make the socket available for a takesocket() call. The giving program passes its client ID, the descriptor of the socket to be given, and the giving program's PID to the taking program by the taking program's startup parameter list.
  2. The taking program sets the c_pid.pid in the clientid structure to the PID of the giving program to identify the process from which the socket is to be taken. If the c_reserved.type field was set to SO_CLOSE on givesocket(), the c_close.SockToken should be used as input to the takesocket() instead of the normal socket descriptor. The taking program calls takesocket(), specifying the giving program's client ID and either the socket descriptor or c_close.SockToken.
  3. If the c_reserved.type field in the clientid structure was set to SO_CLOSE on the givesocket() call, the socket is closed and the giving program does not have to wait for the taking program to issue the takesocket(). Otherwise, steps 3 and 4 of "Using name and subtaskname for givesocket/takesocket" should be followed.

Returned value

If successful, givesocket() returns 0.

If unsuccessful, givesocket() returns -1 and sets errno to one of the following values:
Error Code
Description
EBADF
The d parameter is not a valid socket descriptor. The socket has already been given.
EFAULT
Using the clientid parameter as specified would result in an attempt to access storage outside the caller's address space.
EINVAL
The clientid parameter does not specify a valid client identifier or the clientid domain does not match the domain of the input socket descriptor.

Related information