Computer Science
CMSG(3) Linux Programmer's Manual CMSG(3)
NAME
CMSG_ALIGN, CMSG_SPACE, CMSG_NXTHDR, CMSG_FIRSTHDR -
Access ancillary data.
SYNOPSIS
#include <sys/socket.h>
struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *msgh);
struct cmsghdr *CMSG_NXTHDR(struct msghdr *msgh, struct
cmsghdr *cmsg);
size_t CMSG_ALIGN(size_t length);
size_t CMSG_SPACE(size_t length);
size_t CMSG_LEN(size_t length);
void *CMSG_DATA(struct cmsghdr *cmsg);
struct cmsghdr {
socklen_t cmsg_len; /* data byte count, including header */
int cmsg_level; /* originating protocol */
int cmsg_type; /* protocol-specific type */
/* followed by
u_char cmsg_data[]; */
};
DESCRIPTION
These macros are used to create and access control mes-
sages (also called ancillary data) that are not a part of
the socket payload. This control information may include
the interface the packet was received on, various rarely
used header fields, an extended error description, or a
file descriptor to be passed to another process. For
instance, control messages can be used to send additional
header fields such as IP options. Ancillary data is sent
by calling sendmsg(2) or received by recvmsg(2). See
their manual pages for more information.
Ancillary data is a sequence of struct cmsghdr structures
with appended data. This sequence should be accessed only
using the macros described in this manual page and never
directly. See the specific protocol man pages for the
available control message types. The maximum ancillary
buffer size allowed per socket can be set using the
net.core.optmem_max sysctl; see socket(4).
To create ancillary data, first initialize the msg_con-
trollen member of the msghdr with the length of the con-
trol message buffer. Then use CMSG_FIRSTHDR on the msghdr
to get the first control message, initialize cmsg_len
(with CMSG_LEN), the other cmsghdr header fields, and the
data portion using CMSG_DATA. Then get the next cmsghdr
using CMSG_NXTHDR or NULL when you ran out of buffer mem-
ory. Finally the msg_controllen field of the msghdr should
be set to the sum of the CMSG_SPACE of the length of all
control messages in the buffer. For more information on
the msghdr, see recvmsg(2).
CMSG_FIRSTHDR returns a pointer to the first cmsghdr in
the ancillary data buffer associated with the passed
msghdr.
CMSG_NXTHDR returns the next valid cmsghdr after the
passed cmsghdr. It returns NULL when there is no valid
data header left. This macro decrements the msghdr length
field by the cmsghdr length.
CMSG_ALIGN, given a length, returns it including the
required alignment. This is a constant expression.
CMSG_SPACE returns the number of bytes an ancillary ele-
ment with payload of the passed data length occupies. This
is a constant expression.
CMSG_DATA returns a pointer to the data portion of a cms-
ghdr.
CMSG_LEN returns the value to store in the cmsg_len member
of the cmsghdr structure, taking into account any neces-
sary alignment. It takes the data length as an argument.
This is a constant expression.
NOTES
When the control message buffer is too short to store all
messages, the MSG_CTRUNC flag is set in the msg_flags mem-
ber of the msghdr.
EXAMPLE
This code looks for the IP_TTL option in a received ancil-
lary buffer:
struct msghdr msgh;
struct cmsghdr *cmsg;
int *ttlptr;
int received_ttl;
/* Receive auxiliary data in msgh */
for (cmsg = CMSG_FIRSTHDR(&msgh);
cmsg != NULL;
cmsg = CMSG_NXTHDR(&msgh,cmsg) {
if (cmsg->cmsg_level == SOL_IP
&& cmsg->cmsg_type == IP_TTL) {
ttlptr = (int *) CMSG_DATA(cmsg);
received_ttl = *ttlptr;
break;
}
}
if (cmsg == NULL) {
/* Error: IP_TTL not enabled or buffer too short or IO error. */
}
This code passes a file descriptor over a Unix socket
using SCM_RIGHTS:
struct msghdr msg = {0};
struct cmsghdr *cmsg;
int myfds[NUM_FD]; /* Contains the file descriptors to pass. */
char buf[CMSG_SPACE(sizeof myfds)]; /* ancillary data buffer */
int *fdptr;
msg.msg_control = buf;
msg.msg_controllen = sizeof buf;
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * NUM_FD);
/* Initialize the payload: */
fdptr = (int *)CMSG_DATA(cmsg);
memcpy(fdptr, myfds, NUM_FD * sizeof(int));
/* Sum of the length of all control messages in the buffer: */
msg.msg_controllen = cmsg->cmsg_len;
NOTES
For portability, ancillary data should be accessed only
using the macros described here. CMSG_ALIGN is a Linux
extension and should be not used in portable programs.
In Linux, CMSG_LEN, CMSG_DATA, and CMSG_ALIGN are constant
expressions (assuming their argument is constant) - this
could be used to declare the size of global variables.
This may be not portable, however.
CONFORMS TO
This ancillary data model conforms to the POSIX.1003.1g
draft, 4.4BSD-Lite, the IPv6 advanced API described in
RFC2292 and the Single Unix specification v2. CMSG_ALIGN
is a Linux extension.
SEE ALSO
sendmsg(2), recvmsg(2) RFC2292
Linux Man Page 2 Oct 1998 1
Back to the index