[ Team LiB ] |
28.4 Raw Socket InputThe first question that we must answer regarding raw socket input is: Which received IP datagrams does the kernel pass to raw sockets? The following rules apply:
When the kernel has an IP datagram to pass to the raw sockets, all raw sockets for all processes are examined, looking for all matching sockets. A copy of the IP datagram is delivered to each matching socket. The following tests are performed for each raw socket and only if all three tests are true is the datagram delivered to the socket:
Notice that if a raw socket is created with a protocol of 0, and neither bind nor connect is called, then that socket receives a copy of every raw datagram the kernel passes to raw sockets. Whenever a received datagram is passed to a raw IPv4 socket, the entire datagram, including the IP header, is passed to the process. For a raw IPv6 socket, only the payload (i.e., no IPv6 header or any extension headers) is passed to the socket (e.g., Figures 28.11 and 28.22).
ICMPv6 Type FilteringA raw ICMPv4 socket receives most ICMPv4 messages received by the kernel. But ICMPv6 is a superset of ICMPv4, including the functionality of ARP and IGMP (Section 2.2). Therefore, a raw ICMPv6 socket can potentially receive many more packets compared to a raw ICMPv4 socket. But most applications using a raw socket are interested in only a small subset of all ICMP messages. To reduce the number of packets passed from the kernel to the application across a raw ICMPv6 socket, an application-specified filter is provided. A filter is declared with a datatype of struct icmp6_filter, which is defined by including <netinet/icmp6.h>. The current filter for a raw ICMPv6 socket is set and fetched using setsockopt and getsockopt with a level of IPPROTO_ICMPv6 and an optname of ICMP6_FILTER. Six macros operate on the icmp6_filter structure.
The filt argument to all the macros is a pointer to an icmp6_filter variable that is modified by the first four macros and examined by the final two macros. The msgtype argument is a value between 0 and 255 and specifies the ICMP message type. The SETPASSALL macro specifies that all message types are to be passed to the application, while the SETBLOCKALL macros specifies that no message types are to be passed. By default, when an ICMPv6 raw socket is created, all ICMPv6 message types are passed to the application. The SETPASS macro enables one specific message type to be passed to the application while the SETBLOCK macro blocks one specific message type. The WILLPASS macro returns 1 if the specified message type is passed by the filter, or 0 otherwise; the WILLBLOCK macro returns 1 if the specified message type is blocked by the filter, or 0 otherwise. As an example, consider the following application, which wants to receive only ICMPv6 router advertisements: struct icmp6_filter myfilt; fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); ICMP6_FILTER_SETBLOCKALL (&myfilt); ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &myfilt); Setsockopt (fd, IPPROTO_ICMPV6, ICMP6_FILTER. &myfilt, sizeof (myfilt)); We first block all message types (since the default is to pass all message types) and then pass only router advertisements. Despite our use of the filter, the application must be prepared to receive all types of ICMPv6 packets since any ICMPv6 packets that arrive between the socket and the setsockopt will be added to the receive queue. The ICMP6_FILTER option is simply an optimization. |
[ Team LiB ] |