sendmsg()--Send a Message Over a Socket
BSD 4.3 Syntax
#include <sys/types.h> #include <sys/socket.h> int sendmsg(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 sendmsg(int socket_descriptor, const struct msghdr *message_structure, int flags)
Service Program Name: QSOSRV1
Default Public Authority: *USE
Threadsafe: Yes
The sendmsg() function is used to send data or descriptors or ancillary data or a combination of these 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 written to.
- message_structure
- (I/O) The pointer to the message structure that contains the following:
- The address to which the message is to be sent
- The vector array in which the data to be sent is stored
- The ancillary data(BSD 4.4/UNIX98); or an access rights list in which the descriptors to be sent 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 to which the message is sent. For further information about the structure of socket addresses, see the Sockets 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 to be sent. 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_QOS_CLASSIFICATION_DATA The rest of the buffer is an ip_qos_classification_data structure. This structure is defined in <netinet/ip.h> as: struct ip_qos_classification_data { int ip_qos_version; /* Version of struct */ int ip_qos_classification_scope; /* Classification scope */ int ip_qos_classification_type; /* Classification type */ u_char ip_qos_reserved[12]; /* Reserved */ int ip_qos_appl_token_len; /* Length of appl data */ /* followed by application classification data */ };
For further information about how this structure should be initialized, see the Quality of Service topic collection.This ancillary data type is only supported for sockets with an address family of AF_INET and a type of SOCK_STREAM.
Ancillary Data Types That Apply to the IPv6 Layer (where cmsg_level is IPPROTO_IPV6):
cmsg_type cmsg_data IPV6_ADDR_PREFERENCES The rest of the buffer is an integer specifying the source address selection preferences that should be used. The valid source address selection preference flags are defined in <in.h> as:
#define IPV6_PREFER_SRC_HOME 0x00000001 /* Prefer Home addr */ #define IPV6_PREFER_SRC_COA 0x00000002 /* Prefer Care-of addr */ #define IPV6_PREFER_SRC_TMP 0x00000004 /* Prefer Temp addr */ #define IPV6_PREFER_SRC_PUBLIC 0x00000008 /* Prefer Public addr */ #define IPV6_PREFER_SRC_CGA 0x00000010 /* Prefer CGA addr */ #define IPV6_PREFER_SRC_NONCGA 0x00000020 /* Prefer non-CGA addr */
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_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 this structure should be initialized, see inet6_opt_init() and inet6_opt_append().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 this structure should be initialized, see inet6_opt_init() and inet6_opt_append().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_NEXTHOP The rest of the buffer is an sockaddr_in6 structure. This structure is defined in <netinet/in.h>.
For further information about how this structure should be initialized, see AF_INET6 address family.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 source IPv6 address that the outgoing packet should use.
The ipi6_ifindex field specifies the sending interface index that the outgoing packet should use.
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 this structure should be initialized, see inet6_rth_init() and inet6_rth_add().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_RTHDRDSTOPTS 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 this structure should be initialized, see inet6_rth_init() and inet6_rth_add().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_USE_MIN_MTU The rest of the buffer is an integer specifying if path MTU discovery is to be used. 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 msg_flags field is ignored for sendmsg().
- The address to which the message is to be sent
- flags
- (Input) A flag value that controls the transmission 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_EOR Terminate a record, if supported by the protocol.
MSG_OOB Send data as out-of-band data. Valid only for sockets with an address family of AF_INET or AF_INET6 and type SOCK_STREAM.
MSG_DONTROUTE Bypass routing. Valid only for sockets with address family of AF_INET or AF_INET6. It is ignored for other address families.
Authorities
When the address family of the socket identified by the socket_descriptor is AF_INET and is running IP over SNA, the thread must have retrieve, insert, delete, and update authority to the APPC device. When the thread does not have this level of authority, an errno of EACCES is returned.
The user profile for the thread must have *IOSYSCFG special authority to send ancillary data when:- the cmsg_level field specifies IPPROTO_IPV6 and the cmsg_type field is IPV6_NEXTHOP
- the cmsg_level field specifies IPPROTO_IPV6 and the cmsg_type field is IPV6_RTHDR
Return Value
sendmsg() returns an integer. Possible values are:
- -1 (unsuccessful)
- n (successful), where n is the number of bytes sent.
Error Conditions
When sendmsg() fails, errno can be set to one of the following:
[EACCES] | Permission denied.
The process does not have the appropriate privileges to the destination address. |
[EADDRNOTAVAIL] | Address not available.
A socket with an address family of AF_INET or AF_INET6 is using a connectionless transport service, the socket was not bound. The system tried to bind the socket but could not because a port was not available. |
[EBADF] | Descriptor not valid. |
[ECONNREFUSED] | The destination socket refused an attempted
connect operation.
This error code can only be returned on sockets that use a connectionless transport service. |
[EDESTADDRREQ] | Operation requires destination address.
A destination address has not been associated with the socket pointed to by the socket_descriptor parameter and a destination address was not set in the msghdr structure (pointed to by the message_structure parameter). This error code can only be returned on sockets that use a connectionless transport service. |
[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. |
[EHOSTDOWN] | A remote host is not available.
This error code can only be returned on sockets that use a connectionless transport service. |
[EHOSTUNREACH] | A route to the remote host is not available.
This error code can only be returned on sockets that use a connectionless transport service. |
[EINTR] | Interrupted function call. |
[EINVAL] | Parameter not valid.
This error code indicates one of the following:
|
[EIO] | Input/output error. |
[EISCONN] | A connection has already been established.
A destination address was set, but the socket pointed to by the socket_descriptor parameter already has a destination address associated with it. |
[ELOOP] | A loop exists in symbolic links encountered
during pathname resolution.
This error code refers to the destination address, and can only be returned by sockets that use the AF_UNIX or AF_UNIX_CCSID address family. |
[EMSGSIZE] | Message size out of range.
This error code indicates one of the following:
|
[ENAMETOOLONG] | File name too long.
This error code refers to the destination address, and can only be returned by sockets that use the AF_UNIX or AF_UNIX_CCSID address family. |
[ENETDOWN] | The network is not currently available.
This error code can only be returned on sockets that use a connectionless transport service. |
[ENETUNREACH] | Cannot reach the destination network.
This error code can only be returned on sockets that use a connectionless transport service. |
[ENOBUFS] | There is not enough buffer space for the requested operation. |
[ENOENT] | No such file or directory.
This error code refers to the destination address, and can only be returned by sockets that use the AF_UNIX or AF_UNIX_CCSID address family. |
[ENOSYS] | Function not implemented.
This error code refers to the destination address, and can only be returned by sockets that use the AF_UNIX or AF_UNIX_CCSID address family. |
[ENOTCONN] | Requested operation requires a connection.
This error code can only be returned on sockets that use a connection-oriented transport service. |
[ENOTDIR] | Not a directory.
This error code refers to the destination address, and can only be returned by sockets that use the AF_UNIX or AF_UNIX_CCSID address family. |
[ENOTSOCK] | The specified descriptor does not reference a
socket. |
[EOPNOTSUPP] | Operation not supported.
This error code indicates one of the following:
|
[EPIPE] | Broken pipe. |
[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 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. 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
- sendmsg() is an atomic operation in that it produces one packet of
data each time the call is issued on a connectionless socket. For example, a
sendmsg() to a datagram socket will result in a single datagram.
- A destination address cannot be specified if the socket pointed to by the
socket_descriptor parameter already has a destination address
associated with it. To not specify an address, users must set
the msg_name field to NULL or set the msg_namelen field to
zero. (Not specifying an address by setting the msg_namelen field to
zero is an IBM® extension.)
Note: The msg_name and msg_namelen fields are ignored if the socket is using a connection-oriented transport service.
- If the socket is using a connectionless transport device, the socket is not
bound to an address, and the socket type is SOCK_DGRAM, the system
automatically selects an address (INADDR_ANY or in6addr_any and an available
port number) and binds it to the socket before sending the data. The
IPV6_ADDR_PREFERECES socket option flags set on setsockopt()
will be taken into consideration when selecting the source address on which to
send the outgoing data.
- To broadcast on an AF_INET socket, the socket option
SO_BROADCAST must be set (with a setsockopt()).
- When using a connection-oriented transport service, all errors except
[EUNATCH] and [EUNKNOWN] are mapped to
[EPIPE] on an output operation when either of the following
occurs:
- A connection that is in progress is unsuccessful.
- An established connection is broken.
- A connection that is in progress is unsuccessful.
- If the socket is using an address family of AF_UNIX, the
destination address (which is a path name) is assumed to be in the default
coded character set identifier (CCSID) currently in effect for the job. For
AF_UNIX_CCSID, the destination address is assumed to be in the
format and coded character set identifier (CCSID) specified in the
sockaddr_unc.
- For AF_INET sockets over SNA, type SOCK_DGRAM, if
a datagram can not be delivered, no errors are returned. (As an example, a
datagram might not be delivered if there is no datagram application at the
remote host listening at the requested port.)
- 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 sendmsg() API is mapped to
qso_sendmsg98().
- The following functions can be used to build a routing header for IPV6_RTHDR:
- inet6_rth_space()--Return the Number of Bytes Required for the IPv6 Routing Header
- inet6_rth_init()--Initialize Buffer Data for the IPv6 Routing Header
- inet6_rth_add()--Add an IPv6 Address to the IPv6 Routing Header
- The following functions can be used to build an options header for IPV6_HOPOPTS,
IPV6_DSTOPTS, or IPV6_RTHDRDSTOPTS:
- inet6_opt_init()--Initialize Buffer Data for IPv6 Extension Header
- inet6_opt_append()--Append New Option to IPv6 Extension Header
- inet6_opt_finish()--Finish Adding Options to IPv6 Extension Header
- inet6_opt_set_val()--Insert Data Items into IPv6 Option
- Data options set using ancillary data on sendmsg() are known as non-sticky options.
Non-sticky options apply for only a single datagram. Ancillary data only applies to sockets of type
SOCK_DGRAM and SOCK_RAW. For the datagram being sent,
non-sticky options will override any sticky options that have been set on the
socket using setsockopt().
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
- send()--Send Data
- sendto()--Send Data
- takedescriptor()--Receive Socket Access from Another Job
API introduced: V3R1