📄 rfc2292.txt
字号:
Stevens & Thomas Informational [Page 17]RFC 2292 Advanced Sockets API for IPv6 February 19984.1. The msghdr Structure The msghdr structure is used by the recvmsg() and sendmsg() functions. Its Posix.1g definition is: struct msghdr { void *msg_name; /* ptr to socket address structure */ socklen_t msg_namelen; /* size of socket address structure */ struct iovec *msg_iov; /* scatter/gather array */ size_t msg_iovlen; /* # elements in msg_iov */ void *msg_control; /* ancillary data */ socklen_t msg_controllen; /* ancillary data buffer length */ int msg_flags; /* flags on received message */ }; The structure is declared as a result of including <sys/socket.h>. (Note: Before Posix.1g the two "void *" pointers were typically "char *", and the two socklen_t members and the size_t member were typically integers. Earlier drafts of Posix.1g had the two socklen_t members as size_t, but Draft 6.6 of Posix.1g, apparently the final draft, changed these to socklen_t to simplify binary portability for 64-bit implementations and to align Posix.1g with X/Open's Networking Services, Issue 5. The change in msg_control to a "void *" pointer affects any code that increments this pointer.) Most Berkeley-derived implementations limit the amount of ancillary data in a call to sendmsg() to no more than 108 bytes (an mbuf). This API requires a minimum of 10240 bytes of ancillary data, but it is recommended that the amount be limited only by the buffer space reserved by the socket (which can be modified by the SO_SNDBUF socket option). (Note: This magic number 10240 was picked as a value that should always be large enough. 108 bytes is clearly too small as the maximum size of a Type 0 Routing header is 376 bytes.)4.2. The cmsghdr Structure The cmsghdr structure describes ancillary data objects transferred by recvmsg() and sendmsg(). Its Posix.1g definition is: 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[]; */ }; This structure is declared as a result of including <sys/socket.h>.Stevens & Thomas Informational [Page 18]RFC 2292 Advanced Sockets API for IPv6 February 1998 As shown in this definition, normally there is no member with the name cmsg_data[]. Instead, the data portion is accessed using the CMSG_xxx() macros, as described shortly. Nevertheless, it is common to refer to the cmsg_data[] member. (Note: Before Posix.1g the cmsg_len member was an integer, and not a socklen_t. See the Note in the previous section for why socklen_t is used here.) When ancillary data is sent or received, any number of ancillary data objects can be specified by the msg_control and msg_controllen members of the msghdr structure, because each object is preceded by a cmsghdr structure defining the object's length (the cmsg_len member). Historically Berkeley-derived implementations have passed only one object at a time, but this API allows multiple objects to be passed in a single call to sendmsg() or recvmsg(). The following example shows two ancillary data objects in a control buffer.|<--------------------------- msg_controllen -------------------------->|| ||<----- ancillary data object ----->|<----- ancillary data object ----->||<---------- CMSG_SPACE() --------->|<---------- CMSG_SPACE() --------->|| | ||<---------- cmsg_len ---------->| |<--------- cmsg_len ----------->| ||<--------- CMSG_LEN() --------->| |<-------- CMSG_LEN() ---------->| || | | | |+-----+-----+-----+--+-----------+--+-----+-----+-----+--+-----------+--+|cmsg_|cmsg_|cmsg_|XX| |XX|cmsg_|cmsg_|cmsg_|XX| |XX||len |level|type |XX|cmsg_data[]|XX|len |level|type |XX|cmsg_data[]|XX|+-----+-----+-----+--+-----------+--+-----+-----+-----+--+-----------+--+ ^ |msg_controlpoints here The fields shown as "XX" are possible padding, between the cmsghdr structure and the data, and between the data and the next cmsghdr structure, if required by the implementation.4.3. Ancillary Data Object Macros To aid in the manipulation of ancillary data objects, three macros from 4.4BSD are defined by Posix.1g: CMSG_DATA(), CMSG_NXTHDR(), and CMSG_FIRSTHDR(). Before describing these macros, we show the following example of how they might be used with a call to recvmsg(). struct msghdr msg; struct cmsghdr *cmsgptr;Stevens & Thomas Informational [Page 19]RFC 2292 Advanced Sockets API for IPv6 February 1998 /* fill in msg */ /* call recvmsg() */ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == ... && cmsgptr->cmsg_type == ... ) { u_char *ptr; ptr = CMSG_DATA(cmsgptr); /* process data pointed to by ptr */ } } We now describe the three Posix.1g macros, followed by two more that are new with this API: CMSG_SPACE() and CMSG_LEN(). All these macros are defined as a result of including <sys/socket.h>.4.3.1. CMSG_FIRSTHDR struct cmsghdr *CMSG_FIRSTHDR(const struct msghdr *mhdr); CMSG_FIRSTHDR() returns a pointer to the first cmsghdr structure in the msghdr structure pointed to by mhdr. The macro returns NULL if there is no ancillary data pointed to the by msghdr structure (that is, if either msg_control is NULL or if msg_controllen is less than the size of a cmsghdr structure). One possible implementation could be #define CMSG_FIRSTHDR(mhdr) \ ( (mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \ (struct cmsghdr *)(mhdr)->msg_control : \ (struct cmsghdr *)NULL ) (Note: Most existing implementations do not test the value of msg_controllen, and just return the value of msg_control. The value of msg_controllen must be tested, because if the application asks recvmsg() to return ancillary data, by setting msg_control to point to the application's buffer and setting msg_controllen to the length of this buffer, the kernel indicates that no ancillary data is available by setting msg_controllen to 0 on return. It is also easier to put this test into this macro, than making the application perform the test.)Stevens & Thomas Informational [Page 20]RFC 2292 Advanced Sockets API for IPv6 February 19984.3.2. CMSG_NXTHDR struct cmsghdr *CMSG_NXTHDR(const struct msghdr *mhdr, const struct cmsghdr *cmsg); CMSG_NXTHDR() returns a pointer to the cmsghdr structure describing the next ancillary data object. mhdr is a pointer to a msghdr structure and cmsg is a pointer to a cmsghdr structure. If there is not another ancillary data object, the return value is NULL. The following behavior of this macro is new to this API: if the value of the cmsg pointer is NULL, a pointer to the cmsghdr structure describing the first ancillary data object is returned. That is, CMSG_NXTHDR(mhdr, NULL) is equivalent to CMSG_FIRSTHDR(mhdr). If there are no ancillary data objects, the return value is NULL. This provides an alternative way of coding the processing loop shown earlier:struct msghdr msg;struct cmsghdr *cmsgptr = NULL;/* fill in msg *//* call recvmsg() */while ((cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) != NULL) { if (cmsgptr->cmsg_level == ... && cmsgptr->cmsg_type == ... ) { u_char *ptr; ptr = CMSG_DATA(cmsgptr); /* process data pointed to by ptr */ }} One possible implementation could be: #define CMSG_NXTHDR(mhdr, cmsg) \ ( ((cmsg) == NULL) ? CMSG_FIRSTHDR(mhdr) : \ (((u_char *)(cmsg) + ALIGN((cmsg)->cmsg_len) \ + ALIGN(sizeof(struct cmsghdr)) > \ (u_char *)((mhdr)->msg_control) + (mhdr)->msg_controllen) ? \ (struct cmsghdr *)NULL : \ (struct cmsghdr *)((u_char *)(cmsg) + ALIGN((cmsg)->cmsg_len))) ) The macro ALIGN(), which is implementation dependent, rounds its argument up to the next even multiple of whatever alignment is required (probably a multiple of 4 or 8 bytes).Stevens & Thomas Informational [Page 21]RFC 2292 Advanced Sockets API for IPv6 February 19984.3.3. CMSG_DATA unsigned char *CMSG_DATA(const struct cmsghdr *cmsg); CMSG_DATA() returns a pointer to the data (what is called the cmsg_data[] member, even though such a member is not defined in the structure) following a cmsghdr structure. One possible implementation could be: #define CMSG_DATA(cmsg) ( (u_char *)(cmsg) + \ ALIGN(sizeof(struct cmsghdr)) )4.3.4. CMSG_SPACE unsigned int CMSG_SPACE(unsigned int length); This macro is new with this API. Given the length of an ancillary data object, CMSG_SPACE() returns the space required by the object and its cmsghdr structure, including any padding needed to satisfy alignment requirements. This macro can be used, for example, to allocate space dynamically for the ancillary data. This macro should not be used to initialize the cmsg_len member of a cmsghdr structure; instead use the CMSG_LEN() macro. One possible implementation could be: #define CMSG_SPACE(length) ( ALIGN(sizeof(struct cmsghdr)) + \ ALIGN(length) )4.3.5. CMSG_LEN unsigned int CMSG_LEN(unsigned int length); This macro is new with this API. Given the length of an ancillary data object, CMSG_LEN() returns the value to store in the cmsg_len member of the cmsghdr structure, taking into account any padding needed to satisfy alignment requirements. One possible implementation could be: #define CMSG_LEN(length) ( ALIGN(sizeof(struct cmsghdr)) + length )Stevens & Thomas Informational [Page 22]RFC 2292 Advanced Sockets API for IPv6 February 1998 Note the difference between CMSG_SPACE() and CMSG_LEN(), shown also in the figure in Section 4.2: the former accounts for any required padding at the end of the ancillary data object and the latter is the actual length to store in the cmsg_len member of the ancillary data object.4.4. Summary of Options Described Using Ancillary Data There are six types of optional information described in this document that are passed between the application and the kernel using ancillary data: 1. the send/receive interface and source/destination address, 2. the hop limit, 3. next hop address, 4. Hop-by-Hop options, 5. Destination options, and 6. Routing header. First, to receive any of this optional information (other than the next hop address, which can only be set), the application must call setsockopt() to turn on the corresponding flag: int on = 1; setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -