The socket options on the IPPROTO_IP level pertain to attributes specific to the IPv4 protocol, such as modifying certain fields in the IPv4 header and adding a socket to an IPv4 multicast group. Many of these options are declared in both WINSOCK.H and WINSOCK2.H with different values. Note that if you load Winsock 1, you must include the correct header and link with Wsock32.lib. Likewise for Winsock 2, you should include the Winsock 2 header file and link with Ws2_32.lib. This is especially relevant to multicasting, which is available under both versions. Multicasting is supported on all Windows platforms except Windows CE, in which it is available on versions 2.1 and later. The new IGMPv3-related multicasting options are defined in Ws2tcpip.h.
optval Type | Get/Set | Winsock Version | Description |
char [] | Both | 1+ | Gets or sets IP options within the IP header |
This flag allows you to set various IP options within the IP header. Some of the possible options are:
-
Security and handling restrictions. RFC 1108.
-
Record route. Each router adds its IPv4 address to the header (see the ping sample in Chapter 11).
-
Timestamp. Each router adds its IPv4 address and time.
-
Loose source routing. The packet is required to visit each IPv4 address listed in the option header.
-
Strict source routing. The packet is required to visit only those IPv4 addresses listed in the option header.
Be aware that hosts and routers do not support all of these options.
When setting an IPv4 option, the data that you pass into the setsockopt call follows the structure shown in Figure 7-2. The IPv4 option header can be up to 40 bytes long.
The code field indicates which type of IP option is present. For example, the value 0x7 represents the record route option. Length is simply the length of the option header, and offset is the offset value into the header where the data portion of the header begins. The data portion of the header is specific to the particular option. In the following code snippet, we set up the record route option. Notice that we declare a structure (struct ip_option_hdr) that contains the first three option values (code, length, offset), and then we declare the option-specific data as an array of nine unsigned long integers because the data to be recorded is up to nine IPv4 addresses. Remember that the maximum size of the IPv4 option header is 40 bytes; however, our structure occupies only 39 bytes. The system will pad the header to a multiple of a 32-bit word for you (up to 40 bytes).
struct ip_option_hdr { unsigned char code; unsigned char length; unsigned char offset; unsigned long addrs[9]; } opthdr; ... ZeroMemory((char *)&opthdr, sizeof(opthdr)); opthdr.code = 0x7; opthdr.length = 39; opthdr.offset = 4; // Offset to first address (addrs) ret = setsockopt(s, IPPROTO_IP, IP_OPTIONS, (char *)&opthdr, sizeof(opthdr));
Once the option is set, it applies to any packets sent on the given socket. At any pointer thereafter, you can call getsockopt with IP_OPTIONS to retrieve which options were set; however, this will not return any data filled into the option-specific buffers. To retrieve the data set in the IPv4 options, either the socket must be created as a raw socket (SOCK_RAW) or the IP_HDRINCL option should be set—in which case, the IPv4 header is returned along with data after a call to a Winsock receive function.
optval Type | Get/Set | Winsock Version | Description |
BOOL | Both | 2+ | If TRUE, IP header is submitted with data to Winsock send calls. |
Setting the IP_HDRINCL option to TRUE causes the send function to include the IPv4 header ahead of the data Thus, when you call a Winsock send function, you must include the entire IPv4 header ahead of the data and fill each field of the IP header correctly. Note that the IPv4 network stack will fragment the data portion of the packet if necessary when this option is set. This option is valid only for sockets of type SOCK_RAW. Figure 7-3 shows what the IPv4 header should look like. This option is available only in Windows 2000 and later versions.
The first field of the header is the IPv4 version, which is 4. The header length is the number of 32-bit words in the header. An IP header must always be a multiple of 32 bits. The next field is the type of service field. Consult the IP_TOS socket option, discussed in the next section, for more information. The total length field is the length in bytes of the IP header and data. The identification field is a unique value used to identify each IPv4 packet sent. Normally, the system increments this value with each packet sent. The flags and fragmentation offset fields are used when IPv4 packets are fragmented into smaller packets. The TTL limits the number of routers through which the packet can pass. Each time a router forwards the packet, the TTL is decremented by 1. Once the TTL is 0, the packet is dropped. This limits the amount of time a packet can be live on the network. The protocol field is used to demultiplex incoming packets. Some of the valid protocols that use IP addressing are TCP, UDP, IGMP, and ICMP. The checksum is the 16-bit one's complement sum of the header. It is calculated over the header only and not the data. The next two fields are the 32-bit IP source and destination addresses. The IPv4 options field is a variable length field that contains optional information, usually regarding security or routing.
The easiest way to include an IPv4 header with the data you are sending is to define a structure that contains the IP header and the data and pass it into the Winsock send call. See Chapter 11 for more details and an example of this option. This option works only in Windows 2000 and later versions.
optval Type | Get/Set | Winsock Version | Description |
int | Both | 1+ | IPv4 type of service |
The type of service (TOS) is a field present in the IPv4 header that is used to signify certain characteristics of a packet. The field is eight bits long and is broken into three parts: a 3-bit precedence field (which is ignored), a 4-bit TOS field, and the remaining bit (which must be 0). The four TOS bits are minimize delay, maximize throughput, maximize reliability, and minimize monetary costs. Only one bit can be set at a time. All four bits being 0 implies normal service. RFC 1340 specifies the recommended bits to set for various standard applications such as TCP, SMTP, and NNTP. In addition, RFC 1349 contains some corrections to the original RFC.
Interactive applications—such as Rlogin or Telnet—might want to minimize delay. Any kind of file transfer—such as FTP—is interested in maximum throughput. Maximum reliability is used by network management (Simple Network Management Protocol, or SNMP) and routing protocols. Finally, Usenet news (Network News Transfer Protocol, or NNTP) is an example of minimizing monetary costs. The IP_TOS option is not available in Windows CE.
There is another issue when you attempt to set the TOS bits on a QOS-enabled socket. Because IP precedence is used by QOS to differentiate levels of service, it is undesirable to allow developers the capability to change these values. As a result, when you call setsockopt with IP_TOS on a QOS-enabled socket, the QOS service provider intercepts the call to verify whether the change can take place. See Chapter 10 for more information about QOS.
optval Type | Get/Set | Winsock Version | Description |
int | Both | 1+ | IP TTL parameter |
The TTL field is present in an IP header. Datagrams use the TTL field to limit the number of routers through which the datagram can pass. The purpose of this limitation is to prevent routing loops in which datagrams can spin in circles forever. The idea behind this is that each router that the datagram passes through decrements the datagram's TTL value by 1. When the value equals 0, the datagram is discarded. This option is not available in Windows CE.
optval Type | Get/Set | Winsock Version | Description |
unsigned long | Both | 1+ | Gets or sets the local interface for outgoing multicast data |
The IP multicast interface (IF) option sets which local interface multicast data will be sent from. This option is only of interest on machines that have more than one connected network interface (such as network card or modem). The optval parameter should be an unsigned long integer representing the binary IP address of the local interface. The function inet_addr can be used to convert a string IP dotted decimal address to an unsigned long integer, as in the following sample:
DWORD mcastIF; // First join socket s to a multicast group mcastIF = inet_addr("129.113.43.120"); ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char *)&mcastIF, sizeof(mcastIF));
optval Type | Get/Set | Winsock Version | Description |
int | Both | 1+ | Gets or sets the TTL on multicast packets for this socket |
Similar to the IP TTL, this option performs the same function except that it applies only to multicast data sent using the given socket. Again, the purpose of the TTL is to prevent routing loops, but in the case of multicasting, setting the TTL narrows the scope of how far the data will travel. Therefore, multicast group members must be within “range” to receive datagrams. The default TTL value for multicast datagrams is 1.
optval Type | Get/Set | Winsock Version | Description |
BOOL | Both | 1+ | If TRUE, data sent to a multicast address will be echoed to the socket's incoming buffer. |
By default, when you send IP multicast data, the data will be looped back to the sending socket if it is also a member of that multicast group. If you set this option to FALSE, any data sent will not be posted to the incoming data queue for the socket.
optval Type | Get/Set | Winsock Version | Description |
struct ip_mreq | Set only | 1+ | Adds the socket to the given IP group membership |
This option is the Winsock 1 method of adding a socket to an IP multicast group. This is done by creating a socket of address family AF_INET and the socket type SOCK_DGRAM with the socket function. To add the socket to a multicast group, use the following structure.
struct ip_mreq { struct in_addr imr_multiaddr; struct in_addr imr_interface; };
In the ip_mreq structure, imr_multiaddr is the binary address of the multicast group to join, while imr_interface is the local interface on which the group is joined. See Chapter 9 for more information about valid multicast addresses. The imr_interface field is either the binary IPv4 address of a local interface or the value INADDR_ANY, which can be used to select the default interface (according to the routing table).
optval Type | Get/Set | Winsock Version | Description |
struct ip_mreq | Set only | 1+ | Removes the socket from the given IP group membership |
This option is the opposite of IP_ADD_MEMBERSHIP. By calling this option with an ip_mreq structure that contains the same values used when joining the given multicast group, the socket s will be removed from the given group. Chapter 9 contains much more detailed information on IP multicasting.
optval Type | Get/Set | Winsock Version | Description |
struct ip_mreq_source | Set only | 2+ | Joins a multicast group but accepts data from only the given source |
This multicast option joins the specified multicast group on the given interface but will accept data from only the given source IPv4 address (this is know as an include list). This option may be called multiple times to build an include list of multiple acceptable sources. The input structure is defined as
struct ip_mreq_source { struct in_addr imr_multiaddr; struct in_addr imr_sourceaddr; struct in_addr imr_interface };
The first field is the 32-bit multicast address, the second field is the 32-bit IPv4 address of the acceptable source, and the last field is the 32-bit IPv4 address of the local interface on which to join the group.
This option is supported on Windows XP and later versions and requires the local network to be IGMPv3 enabled. See Chapter 9 for more details.
optval Type | Get/Set | Winsock Version | Description |
struct ip_mreq_source | Set only | 2+ | Remove the given IPv4 source from the list of acceptable sources |
This option is the complement to IP_ADD_SOURCE_MEMBERSHIP. Once one or more sources for a particular multicast group are added via IP_ADD_SOURCE_MEMBERSHIP, this option can be used to remove selected sources from the include list. Using these two options, an application can manage the list of sources to accept multicast data from a given multicast address. This option requires Windows XP and an IGMPv3-enabled network. See Chapter 9 for more details.
optval Type | Get/Set | Winsock Version | Description |
struct ip_mreq_source | Set only | 2+ | Joins a multicast group but accepts data from everyone except the given IPv4 source |
This and the IP_UNBLOCK_SOURCE options are used to build an exclude list of sources for multicast traffic. The IP_BLOCK_SOURCE specifies a source from which multicast data will not be accepted. This option may be called multiple times to exclude additional sources. This option requires Windows XP and an IGMPv3-enabled network. See Chapter 9 for more details.
optval Type | Get/Set | Winsock Version | Description |
struct ip_mreq_source | Both | 2+ | Adds the given IPv4 source to the list of acceptable sources |
This option removes the given source from the exclude list so that multicast data received from the removed source will be propagated to the socket. This option requires Windows XP and an IGMPv3-enabled network. See Chapter 9 for more details.
optval Type | Get/Set | Winsock Version | Description |
BOOL | Both | 1+ | If TRUE, do not fragment IP datagrams. |
This flag tells the network not to fragment the IPv4 datagram during transmission. However, if the size of the IPv4 datagram exceeds the maximum transmission unit (MTU) and the IP don't fragment flag is set within the IPv4 header, the datagram will be dropped and an ICMP error message (“fragmentation needed but don't fragment bit set”) will be returned to the sender. This option is not available on Windows CE.
optval Type | Get/Set | Winsock Version | Description |
int | Set only | 2+ | Indicates whether packet information should be returned from WSARecvMsg |
This option indicates that IPv4 packet information should be returned as a part of the control buffer passed to the WSARecvMsg API. This function was discussed in Chapter 6. For IPv4, the structure returned is the IN_PKTINFO defined as
typedef struct in_pktinfo { IN_ADDR ipi_addr; UINT ipi_ifindex; } IN_PKTINFO;
The first field is the 32-bit binary IPv4 address on which the packet was received. The second field is the interface index that can be correlated to a particular network adapter via the IP Helper APIs discussed in Chapter 16.
The IPPROTO_IPV6 level indicates socket options that pertain to the IPv6 protocol. Many of these options mirror the IPv4 socket options. These values are defined in WS2TCPIP.H.
optval Type | Get/Set | Winsock Version | Description |
BOOL | Both | 2+ | If TRUE, IPv6 header is submitted to Winsock send calls. |
This option indicates that the application will supply the IPv6 header for each packet of data sent by a Winsock send call. The IPv6 stack will not perform any fragmentation for packets larger than the MTU. Applications must build the appropriate fragmentation headers for each packet sent that is larger than the MTU. This socket option is valid only for sockets of type SOCK_RAW. On IPv6, raw sockets are truly raw. Figure 7-4 shows the IPv6 header.
The first field is four bits in length and is the IP version which is six. The next 8-bit field defines the traffic class. Currently, there are no well-defined values for this field. The 20-bit flow label is used to label sequences of packets that request special treatment. Again, there are no predefined values for this field. The 16-bit payload field is the length of the payload in octets. This includes any extension headers but not the basic IPv6 header itself. The 8-bit next header field indicates the protocol value of the next header. This can either be an IPv6 extension header (such as the fragmentation header) or the next encapsulated protocol (such as UDP or TCP). The 8-bit hop limit field indicates the TTL value for the packet. The last two fields are the 128-bit source and destination IPv6 addresses. See Chapter 11 for examples of using the IPV6_HDRINCL option.
optval Type | Get/Set | Winsock Version | Description |
int | Both | 2+ | IPv6 TTL parameter |
This option is used to set the TTL value to be used on unicast traffic sent on the socket. This is analogous to the IPv4 option IP_TTL.
optval Type | Get/Set | Winsock Version | Description |
int | Both | 2+ | IPv6 multicast interface for outgoing multicast data |
This option is analogous to the IP_MULTICAST_IF option except that it sets the outgoing interface for IPv6 multicast traffic. Also, instead of specifying the local IPv6 interface address for the outgoing traffic, the interface's scope ID is specified instead. The IP Helper function GetAdaptersAddress can be called to obtain the local interface indices. Chapter 9 covers IPv6 multicasting in more detail and Chapter 16 discusses the IP Helper APIs.
optval Type | Get/Set | Winsock Version | Description |
int | Both | 2+ | IPv6 TTL parameter for multicast data |
This option is analogous to the IP_MULTICAST_TTL option except that it sets the TTL option for IPv6 multicast traffic.
optval Type | Get/Set | Winsock Version | Description |
int | Both | 2+ | If TRUE, data sent to a multicast address will be echoed to the socket's incoming buffer. |
This option enables outgoing IPv6 multicast traffic to be echoed back to the sending socket if the sending socket is also a member of the multicast group. This option is analogous to the IPv4 multicast option IP_MULTICAST_LOOP.
optval Type | Get/Set | Winsock Version | Description |
struct ipv6_mreq | Both | 2+ | Joins an IPv6 multicast group on the specified interface |
This option joins the IPv6 multicast group on a particular interface. The input parameter is defined as
typedef struct ipv6_mreq { struct in6_addr ipv6mr_multiaddr; unsigned int ipv6mr_interface; } IPV6_MREQ;
The first field is the IPv6 address of the multicast address to join, and the second field is the interface index (or scope ID) on which to join the group. See Chapter 9 for more information.
optval Type | Get/Set | Winsock Version | Description |
struct ipv6_mreq | Both | 2+ | Drops the multicast group from the given interface |
This option drops membership of the IPv6 multicast group from the given interface. The input parameter is the struct ipv6_mreq containing the multicast group to drop from the given interface (scope ID). See Chapter 9 for more information.
optval Type | Get/Set | Winsock Version | Description |
int | Both | 2+ | Indicates whether packet information should be returned from WSARecvMsg |
This option indicates that IPv6 packet information should be returned as a part of the control buffer passed to the WSARecvMsg API. This function was discussed in Chapter 6. For IPv6, the structure returned is the IN6_PKTINFO defined as
typedef struct in6_pktinfo { IN6_ADDR ipi6_addr; UINT ipi6_ifindex; } IN6_PKTINFO;
The first field is the binary IPv6 address on which the packet was received. The second field is the interface index that can be correlated to a particular network adapter via the IP Helper APIs discussed in Chapter 16.