Showing posts with label IPC - Socket : Advance Concept. Show all posts
Showing posts with label IPC - Socket : Advance Concept. Show all posts

Thursday, February 23, 2012

ancillary data definition

Although it is very difficult to prove the identity of a remote user over the Internet, it is a simple matter for the Linux kernel to identify another user on the same host. This makes it possible for PF_LOCAL/PF_UNIX sockets to provide credentials to the receiving end about the user at the other end. The only way for these credentials to be compromised would be for the kernel itself to be compromised in some way (perhaps by a rogue kernel loadable module).

Credentials can be received as part of ancillary data that is received with a communication. Ancillary data is supplementary or auxiliary to the normal data. This brings up some points that are worth emphasizing here:
  • Credentials are received as part of ancillary data.
  • Ancillary data must accompany normal data (it cannot be transmitted on its own).
  • Ancillary data can also include other information such as file descriptors.
  • Ancillary data can include multiple ancillary items together (such as credentials and file descriptors at the same time).
The credentials are provided by the Linux kernel. They are never provided by the client application. If they were, the client would be allowed to lie about its identity. Because the kernel is trusted, the credentials can be trusted by the process that is interested in the credentials. As noted in the list, you now know that file descriptors are also transmitted and received as ancillary data. However, before you can start writing socket code to use these elements of ancillary data, you need to be introduced to some new programming concepts.
TIP
Ancillary data is referred to by several different terms. Other names for ancillary data include auxiliary or control data. In the context of PF_LOCAL/PF_UNIX sockets, these all refer to the same thing.

See Also:

Tuesday, February 21, 2012

cmsg macro

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);
unsigned char *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 unsigned char cmsg_data[]; */
};

DESCRIPTION
These  macros  are  used to create and access control messages (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,  a  set  of  file  descriptors or Unix credentials.  For instance, control messages can be used to send additional header fields such as IP options.  Ancillary data is sent by calling sendmsg and received by calling recvmsg.
Ancillary  data is a sequence of struct cmsghdr structures with appended data.  This sequence should only be accessed 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 /proc/sys/net/core/optmem_max;.

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 isnât enough space left in the buffer.


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 element with payload of the passed data length occupies.   This  is  a  constant expression.


CMSG_DATA() returns a pointer to the data portion of a cmsghdr.

CMSG_LEN()  returns  the  value to store in the cmsg_len member of the cmsghdr structure, taking into account any necessary alignment.
It takes the data length as an argument.  This is a constant expression.

To create ancillary data, first initialize the msg_controllen member of the msghdr with the length of the control message buffer.  Use CMSG_FIRSTHDR()  on  the  msghdr to get the first control message and CMSG_NEXTHDR() to get all subsequent ones.  In each control message, initialize cmsg_len (with CMSG_LEN()), the other cmsghdr header fields, and the data portion using  CMSG_DATA().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.


When the control message buffer is too short to store all messages, the MSG_CTRUNC flag is set in the msg_flags member of the  msghdr.

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.

See Also:

struct cmsghdr cmsg

Introducing the struct cmsghdr Structure

Ancillary information can include zero, one, or more separate ancillary data objects. Each of these objects is preceded by a struct cmsghdr. This header is followed possibly by pad bytes and
then the object itself. Finally, the ancillary data object itself might be followed by still more pad bytes before the next cmsghdr follows. In this post, the only ancillary data objects that you'll be concerned about will be the file descriptor and a credentials structure.

Figure below illustrates how a buffer containing ancillary data is structured.
Note the following additional points about below Figure :
  • The value of cmsg_len is equivalent to the length shown as the macro value for CMSG_LEN() in Figure below.
  • The macro CMSG_SPACE() computes the total necessary space required for one ancillary data object.
  • The value of msg_controllen is the sum of the CMSG_SPACE() lengths, and is computed for each ancillary data object.
 

                             Figure:
Ancillary data structures are composed of various substructures, data zones, and pad•bytes.

The control message header itself is defined as the following C structure:

struct cmsghdr {
   socklen_t cmsg_len;
   int cmsg_level;
   int cmsg_type;
   /* u_char cmsg_data[]; */
};

Table a: The struct cmshdr Members
Member
Description
cmsg_len
This is the byte count of the ancillary data, which includes the size of this structural header. This value is computed by the CMSG_LEN() macro.
cmsg_level
This value indicates the originating protocol level (for example, SOL_SOCKET).
cmsg_type
This value indicates the control message type (for example, SCM_RIGHTS).
cmsg_data
This member does not actually exist. It is shown in comments to illustrate where additional ancillary data is located physically.

The example programs used in this chapter will use only a cmsg_level value of SOL_SOCKET. The control message types that are of interest to you in this chapter are shown in Table b.

Table b: cmsg_type Types for cmsg_level=SOL_SOCKET

cmsg_level
Description
SCM_RIGHTS
The ancillary data object is a file descriptor.
SCM_CREDENTIALS
The ancillary data object is a structure containing credential information.

See Also: