recvmsg()--Receive a Message Over a Socket
BSD 4.3 Syntax
#include <sys/types.h> #include <sys/socket.h> int recvmsg(int socket_descriptor, struct msghdr *message_structure, int flags)
Service Program Name: QSOSRV1
Default Public Authority: *USE
Threadsafe: Yes
UNIX® 98 Compatible Syntax
#define _XOPEN_SOURCE 520 #include <sys/socket.h> ssize_t recvmsg(int socket_descriptor, struct msghdr *message_structure, int flags)
Service Program Name: QSOSRV1
Default Public Authority: *USE
Threadsafe: Yes
The recvmsg() function is used to receive data or descriptors or both through a connected or unconnected socket.
There are two versions of the API, as shown above. The base IBM® i API uses BSD 4.3 structures and syntax. The other uses syntax and structures compatible with the UNIX 98 programming interface specifications. You can select the UNIX 98 compatible interface with the _XOPEN_SOURCE macro.
Parameters
- socket_descriptor
- (Input) The socket descriptor that is to be read from.
- message_structure
- (I/O) The pointer to the message structure that contains the following:
- The address from which the message was received
- The vector array in which the data received is stored
- The ancillary data(BSD 4.4/UNIX98); or an access rights list in which the descriptors received are stored.
The BSD 4.3 structure is:
struct msghdr { caddr_t msg_name; int msg_namelen; struct iovec *msg_iov; int msg_iovlen; caddr_t msg_accrights; int msg_accrightslen; };
The BSD 4.4/UNIX 98 compatible structure is:
struct msghdr { void *msg_name; socklen_t msg_namelen; struct iovec *msg_iov; int msg_iovlen; void *msg_control; /* Set to NULL if not needed */ socklen_t msg_controllen; /* Set to 0 if not needed */ int msg_flags; };
The msg_name and msg_namelen fields contain the address and address length from which the message was received. For further information about the structure of socket addresses, see the Socket programming topic collection. If the msg_name field is set to a NULL pointer, the address information is not returned.
The msg_iov and msg_iovlen fields are for scatter/gather I/O.
The BSD 4.3 structure uses the msg_accrights and msg_accrightslen fields to pass descriptors. The msg_accrights field is a list of zero or more descriptors, and msg_accrightslen is the total length (in bytes) of the descriptor list.
The BSD 4.4/UNIX 98 compatible structure uses the msg_control and msg_controllen fields to pass ancillary data. The msg_control field is a pointer to ancillary data (of length msg_controllen) with the form:
struct cmsghdr { socklen_t cmsg_len; /* # bytes, including this header */ int cmsg_level; /* originating protocol */ int cmsg_type; /* protocol-specific type */ /* followed by unsigned char cmsg_data[]; */ };
The cmsg_len field is the total length including this header. cmsg_level is the originating protocol. cmsg_type is the protocol-specific type. If ancillary data and descriptors are not being passed, the msg_control field must be initialized to NULL and the msg_controllen field must be initialized to 0. The following tables list the supported ancillary data types when using the BSD 4.4/UNIX 98 compatible structures.
Ancillary Data Types That Apply to the Socket Layer (where cmsg_level is SOL_SOCKET ):
cmsg_type cmsg_data SCM_RIGHTS The rest of the buffer is a list of zero or more descriptors received. This ancillary data type is only supported for sockets with an address family of AF_UNIX or AF_UNIX_CCSID.
Ancillary Data Types That Apply to the IP Layer (where cmsg_level is IPPROTO_IP):
cmsg_type cmsg_data IP_PKTINFO The rest of the buffer is an in_pktinfo structure. This structure is defined in <netinet/in.h> as: struct in_pktinfo { struct in_addr ipi_addr; /* IPv4 destination address */ struct in_addr ipi_interface; /* Interface which pkt was rcvd */ };
The ipi_addr field specifies the IPv4 destination address.
The ipi_interface field specifies the interface on which the packet was received.
This ancillary data type is only supported for sockets with an address family of AF_INET and a type of SOCK_DGRAM or SOCK_RAW.
Ancillary Data Types That Apply to the IPv6 Layer (where cmsg_level is IPPROTO_IPV6):
cmsg_type cmsg_data IPV6_DSTOPTS The rest of the buffer is an ip6_dest structure. This structure is defined in <netinet/ip6.h> as: struct ip6_dest { uint8_t ip6d_nxt; /* next header */ uint8_t ip6d_len; /* length in units of 8 octets */ /* followed by options */ };
The ip6d_nxt field specifies the option type of the next header in the chain of headers.
The ip6d_len field specifies the length of the destination header in units of 8 octets, not including the first 8 octets.
For further information about how to parse this structure, see inet6_opt_next().This ancillary data type is only supported for sockets with an address family of AF_INET6 and a type of SOCK_DGRAM or SOCK_RAW.
IPV6_HOPOPTS The rest of the buffer is an ip6_hbh structure. This structure is defined in <netinet/ip6.h> as: struct ip6_hbh { uint8_t ip6h_nxt; /* next header */ uint8_t ip6h_len; /* length in units of 8 octets */ /* followed by options */ };
The ip6h_nxt field specifies the offset of the next header in the chain of headers.
The ip6h_len field specifies the length of the hop-by-hop header in units of 8 octets, not including the first 8 octets.
For further information about how to parse this structure, see inet6_opt_next().This ancillary data type is only supported for sockets with an address family of AF_INET6 and a type of SOCK_DGRAM or SOCK_RAW.
IPV6_HOPLIMIT The rest of the buffer is an integer specifying the hop limit. This ancillary data type is only supported for sockets with an address family of AF_INET6 and a type of SOCK_DGRAM or SOCK_RAW.
IPV6_PKTINFO The rest of the buffer is an in6_pktinfo structure. This structure is defined in <netinet/in.h> as: struct in6_pktinfo { struct in6_addr ipi6_addr; /* Src/dst IPv6 address */ unsigned int ipi6_ifindex; /* Send/recv interface index */ };
The ipi6_addr field specifies the destination IPv6 address that the incoming packet came in on.
The ipi6_ifindex field specifies the receiving interface index that the incoming packet came in on.
This ancillary data type is only supported for sockets with an address family of AF_INET6 and a type of SOCK_DGRAM or SOCK_RAW.
IPV6_RTHDR The rest of the buffer is an ip6_rthdr structure. This structure is defined in <netinet/ip6.h> as: struct ip6_rthdr { uint8_t ip6r_nxt; /* next header */ uint8_t ip6r_len; /* length in units of 8 octets */ uint8_t ip6r_type; /* routing type */ uint8_t ip6r_segleft; /* segments left */ /* followed by routing type specific data */ };
The ip6r_nxt field specifies the offset of the next header in the chain of headers.
The ip6r_len field specifies the length of the routing header in units of 8 octets, not including the first 8 octets.
The ip6r_type field specifies the routing type.
The ip6r_segleft field that is returned is the number of hops remaining to reach the destination.
For further information about how to parse this structure, see inet6_rth_getaddr().This ancillary data type is only supported for sockets with an address family of AF_INET6 and a type of SOCK_DGRAM or SOCK_RAW.
IPV6_TCLASS The rest of the buffer is an integer specifying the traffic class. This ancillary data type is only supported for sockets with an address family of AF_INET6 and a type of SOCK_DGRAM or SOCK_RAW.
IPV6_PATHMTU The rest of the buffer is an ip6_mtuinfo structure. This structure is defined in <netinet/in.h> as: struct ip6_mtuinfo { struct sockaddr_in6 ip6m_addr; /* Dst addr including zone ID */ uint32_t ip6m_mtu; /* Path MTU in host byte order */ };
The ip6m_addr field that is returned will be the destination address that this socket is connected to.
The ip6m_mtu field that is returned will be the path Maximum Transmission Unit.
This ancillary data item will be received for each ICMP too big error the node receives when the IPV6_RECVPATHMTU option is set.
This ancillary data type is only supported for sockets with an address family of AF_INET6 and a type of SOCK_DGRAM or SOCK_RAW.
Macros are provided for navigating these structures.
- CMSG_DATA(cmsg) If the argument is a pointer to a cmsghdr structure, this macro returns an unsigned character pointer to the data array associated with the cmsghdr structure.
- CMSG_NXTHDR(mhdr,cmsg) If the first argument is a pointer to a msghdr structure and the second argument is a pointer to a cmsghdr structure in the ancillary data, pointed to by the msg_control field of that msghdr structure, this macro returns a pointer to the next cmsghdr structure, or a null pointer if this structure is the last cmsghdr in the ancillary data.
- CMSG_FIRSTHDR(mhdr) If the argument is a pointer to a msghdr structure, this macro returns a pointer to the first cmsghdr structure in the ancillary data associated with this msghdr structure, or a null pointer if there is no ancillary data associated with the msghdr structure.
The BSD 4.4/UNIX 98 compatible structure has the msg_flags for message level flags including:
- MSG_TRUNC Message data was truncated
- MSG_CTRUNC Ancillary data was truncated.
- MSG_EOR End of record (if supported by the protocol).
- MSG_OOB Out-of-band data.
- The address from which the message was received
- flags
- (Input) A flag value that controls the reception of the data. The
flags value is either zero, or is obtained by performing an OR
operation on one or more of the following constants:
MSG_OOB Receive out-of-band data. Valid only for sockets with an address family of AF_INET or AF_INET6 and type SOCK_STREAM. MSG_PEEK Obtain a copy of the message without removing the message from the socket. MSG_WAITALL Wait for a full request or an error.
Authorities
- An errno of EACCES is returned when the socket pointed to by the
socket_descriptor field is address family AF_INET and
a nonblocking connect was attempted previously and was not successful. The
nonblocking connect was not successful because the thread did not have
authority to the associated APPC device. The thread performing the nonblocking
connect must have retrieve, insert, delete, and update authority to the APPC
device.
- If this thread is receiving socket descriptors, it must have *ALLOBJ special authority or must be running under the same user profile as the thread that sent the descriptors using sendmsg. If both of these conditions are not true, the descriptors are reclaimed by the machine and an errno of EACCES is returned.
Return Value
recvmsg() returns an integer. Possible values are:
- -1 (unsuccessful)
- n (successful), where n is the number of bytes received.
Error Conditions
When recvmsg() fails, errno can be set to one of the following:
[EACCES] | Permission denied.
The socket pointed to by the socket_descriptor parameter is using a connection-oriented transport service, and a connect() was previously completed. The process, however, does not have the appropriate privileges to the objects that were needed to establish a connection. For example, the connect() required the use of an APPC device that the process was not authorized to. If the msg_accrights and msg_accrightslen fields (or the BSD 4.4/UNIX 98 compatible fields msg_control and msg_controllen) were specified and descriptors were sent, this error indicates that this job does not have the appropriate privileges required to receive the descriptor. When this occurs, the descriptor is reclaimed by the system and the resource that it represented is closed. |
[EBADF] | Descriptor not valid. |
[ECONNABORTED] | Connection ended abnormally.
This error code indicates that the transport provider ended the connection abnormally because of one of the following:
|
[ECONNREFUSED] | The destination socket refused an attempted
connect operation. |
[ECONNRESET] | A connection with a remote socket was reset by
that socket. |
[EFAULT] | Bad address.
The system detected an address which was not valid while attempting to access the message_structure parameter or a field within the structure pointed to by the message_structure parameter. |
[EINTR] | Interrupted function call. |
[EINVAL] | Parameter not valid.
This error code indicates one of the following:
|
[EIO] | Input/output error. |
[EMFILE] | Too many descriptions for this process. |
[EMSGSIZE] | Message size out of range.
The msg_iovlen field specifies a value that is greater than [MSG_MAXIOVLEN] (defined in <sys/socket.h>). |
[ENOBUFS] | There is not enough buffer space for the
requested operation. |
[ENOTCONN] | Requested operation requires a connection.
This error code is returned only on sockets that use a connection-oriented transport service. |
[ENOTSOCK] | The specified descriptor does not reference a
socket. |
[EOPNOTSUPP] | Operation not supported.
This error code indicates one of the following:
|
[ETIMEDOUT] | A remote host did not respond within the timeout
period.
A non-blocking connect() was previously issued that resulted in the connection establishment timing out. No connection is established. This error code is returned only on sockets that use a connection-oriented transport service. |
[EUNATCH] | The protocol required to support the specified
address family is not available at this time. |
[EUNKNOWN] | Unknown system state. |
[EWOULDBLOCK] | Operation would have caused the thread to be suspended. |
Error Messages
Message ID | Error Message Text |
---|---|
CPE3418 E | Possible APAR condition or hardware failure. |
CPF9872 E | Program or service program &1 in library &2 ended. Reason code &3. |
CPFA081 E | Unable to set return value or error code. |
Usage Notes
- The following applies to sockets that use a connection-oriented transport
service (for example, sockets with a type of SOCK_STREAM),
- The msg_name and msg_namelen fields in the structure
pointed to by the message_structure parameter are ignored.
- A returned value of zero indicates one of the following:
- The partner program has issued a close() for the socket.
- The partner program has issued a shutdown() to disable writing to
the socket.
- The connection is broken and the error was returned on a previously issued
socket function.
- A shutdown() to disable reading was previously done on the socket.
- The partner program has issued a close() for the socket.
- The msg_name and msg_namelen fields in the structure
pointed to by the message_structure parameter are ignored.
- The following applies to sockets that use a connectionless transport
service (for example, a socket with a type of SOCK_DGRAM):
- If a connect() has been issued previously, then data can be
received only from the address specified in the previous
connect().
- If the msg_name field is set to NULL or msg_namelen field
specifies a value of zero, the address from which data is received is
discarded.
- If the length of the address to be returned exceeds the length specified by
the msg_namelen field, the returned address is truncated.
- If the socket is using an address family of AF_UNIX, the
address (which is a path name) is returned in the default coded character set
identifier (CCSID) currently in effect for the job.
- If the socket is using an address family of AF_UNIX_CCSID, the
output structure sockaddr_unc defines the format and coded character set
identifier (CCSID) of the address (which is a path name).
- The entire message must be read in a single read operation. If the size of
the message is too large to fit in the user supplied buffer, the remaining
bytes of the message are discarded.
- A returned value of zero indicates one of the following:
- The partner program has sent a NULL message (a datagram with no user
data).
- A shutdown() to disable reading was previously done on the
socket.
- The buffer length specified was zero.
- The partner program has sent a NULL message (a datagram with no user
data).
- If a connect() has been issued previously, then data can be
received only from the address specified in the previous
connect().
- The passing of descriptors is only supported over sockets that have an
address family of AF_UNIX or AF_UNIX_CCSID. The
msg_accrightslen and the msg_accrights fields (or the
BSD 4.4/UNIX 98 compatible fields msg_control and
msg_controllen) are ignored if the socket has any other
address family. The value of msg_accrightslen (or the BSD
4.4/UNIX 98 compatible field msg_controllen)
should be checked to determine if a descriptor has been returned. When you use
sendmsg() and recvmsg() to pass descriptors, the target job
must be running with either of the following:
- The same user profile as the source job (in essence, passing the descriptor to yourself)
- *ALLOBJ special authority
If the target job closes the receiving end of the UNIX domain socket while a descriptor is in transit, the descriptor is reclaimed by the system, and the resource that it represented is closed. For files and directories, the ability to pass descriptors using sendmsg() and recvmsg() is only supported for objects in the Root, QOpenSys, User-defined file systems (UDFS), and Network File System (NFS).
Note: The recvmsg() API will not block unless a data buffer is specified.
- recvmsg() accepts a pointer to an array of iovec
structures in the msghdr structure. The msg_iovlen
field is used to determine the number of elements in the array (the number of
iovec structures specified). When recvmsg() is
issued, the system processes the array elements one at a time, starting with
the first structure. For each element of the array (for each structure),
iov_len bytes of received data are placed in storage pointed to by
iov_base. Data is placed in storage until all buffers are full, or
until there is no more data to receive. Only the memory pointed to by
iov_base is updated. No change is made to the iov_len fields.
To determine the end of the data, the application program must use the
following:
- The function return value (the total number of bytes received).
- The lengths of the buffers pointed to by iov_base.
- The function return value (the total number of bytes received).
- When you develop in C-based
languages and an application is compiled with the _XOPEN_SOURCE macro defined
to the value 520 or greater, the recvmsg() API is mapped to
qso_recvmsg98().
- If this function is called
by a thread executing one of the scan-related exit programs (or any of its
created threads), it will fail with error code [ENOTSUP]. See Integrated File System Scan on Open Exit Programs and Integrated File System Scan on Close Exit Programs
for more information.
- When the descriptor is obtained using recvmsg(), any information
accessed using that descriptor with the various read and write interfaces will
be in binary, even if the original descriptor's accesses would have had text
conversions occur. See
Using CCSIDs and code pages in the
open--Open file documentation for more information about text conversion.
- The following functions can be used to parse a routing header for
IPV6_RTHDR:
- inet6_rth_getaddr()--Retrieve an Address from the IPv6 Routing Header
- inet6_rth_reverse()--Reverse the Order of Addresses in the IPv6 Routing Header
- inet6_rth_segments()--Return the Number of Segments in the IPv6 Routing Header
- The following functions can be used to parse an options header for
IPV6_HOPOPTS, IPV6_DSTOPTS, or
IPV6_RTHDRDSTOPTS:
- inet6_opt_find()--Extract Option of Specified Type from IPv6 Extension Header
- inet6_opt_get_val()--Retrieve Data Items from an IPv6 Option
- inet6_opt_next()--Extract the Next Option from the IPv6 Extension Header
Related Information
- For additional information and sample programs on how to use sendmsg()
and recvmsg() to pass descriptors between jobs, see the Socket programming topic collection.
- _XOPEN_SOURCE--Using _XOPEN_SOURCE for
the UNIX 98 compatible interface
- fcntl()--Perform File Control Command
- ioctl()--Perform I/O Control Request
- givedescriptor()--Pass Descriptor Access to Another
Job
- recv()--Receive Data
- recvfrom()--Receive Data
- takedescriptor()--Receive Descriptor Access from Another Job
API introduced: V3R1