Thursday, October 15, 2009

22.6 in_pcblookup Function

Team-Fly
 

 

TCP/IP Illustrated, Volume 2: The Implementation
By
Gary R. Wright, W. Richard Stevens
Table of Contents
Chapter 22. 
Protocol Control Blocks


22.6 in_pcblookup Function


The function in_pcblookup serves four different purposes.


  1. When either TCP or UDP receives an IP datagram, in_pcblookup scans the protocol's list of Internet PCBs looking for a matching PCB to receive the datagram. This is transport layer demultiplexing of a received datagram.

  2. When a process executes the bind system call, to assign a local IP address and local port number to a socket, in_pcbbind is called by the protocol to verify that the requested local address pair is not already in use.

  3. When a process executes the bind system call, requesting an ephemeral port be assigned to its socket, the kernel picks an ephemeral port and calls in_pcbbind to check if the port is in use. If it is in use, the next ephemeral port number is tried, and so on, until an unused port is located.

  4. When a process executes the connect system call, either explicitly or implicitly, in_pcbbind verifies that the requested socket pair is unique. (An implicit call to connect happens when a UDP datagram is sent on an unconnected socket. We'll see this scenario in Chapter 23.)


In cases 2, 3, and 4 in_pcbbind calls in_pcblookup. Two options confuse the logic of the function. First, a process can specify either the SO_REUSEADDR or SO_REUSEPORT socket option to say that a duplicate local address is OK.


Second, sometimes a wildcard match is OK (e.g., an incoming UDP datagram can match a PCB that has a wildcard for its local IP address, meaning that the socket will accept UDP datagrams that arrive on any local interface), while other times a wildcard match is forbidden (e.g., when connecting to a foreign IP address and port number).



In the original Stanford IP multicast code appears the comment that "The logic of in_pcblookup is rather opaque and there is not a single comment, …" The adjective opaque is an understatement.


The publicly available IP multicast code available for BSD/386, which is derived from the port to 4.4BSD done by Craig Leres, fixed the overloaded semantics of this function by using in_pcblookup only for case 1 above. Cases 2 and 4 are handled by a new function named in_pcbconflict, and case 3 is handled by a new function named in_uniqueport. Dividing the original functionality into separate functions is much clearer, but in the Net/3 release, which we're describing in this text, the logic is still combined into the single function in_pcblookup.



Figure 22.16 shows the in_pcblookup function.



Figure 22.16. in_pcblookup function: search all the PCBs for a match.


The function starts at the head of the protocol's PCB list and potentially goes through every PCB on the list. The variable match remembers the pointer to the entry with the best match so far, and matchwild remembers the number of wildcards in that match. The latter is initialized to 3, which is a value greater than the maximum number of wildcard matches that can be encountered. (Any value greater than 2 would work.) Each time around the loop, the variable wildcard starts at 0 and counts the number of wildcard matches for each PCB.


Compare local port number


416-417

The first comparison is the local port number. If the PCB's local port doesn't match the lport argument, the PCB is ignored.



Compare local address


419-427

in_pcblookup compares the local address in the PCB with the laddr argument. If one is a wildcard and the other is not a wildcard, the wildcard counter is incremented. If both are not wildcards, then they must be the same, or this PCB is ignored. If both are wildcards, nothing changes: they can't be compared and the wildcard counter isn't incremented. Figure 22.17 summarizes the four different conditions.



Figure 22.17. Four scenarios for the local IP address comparison done by in_pcblookup.



Compare foreign address and foreign port number


428-437

These lines perform the same test that we just described, but using the foreign addresses instead of the local addresses. Also, if both foreign addresses are not wildcards then not only must the two IP addresses be equal, but the two foreign ports must also be equal. Figure 22.18 summarizes the foreign IP comparisons.



Figure 22.18. Four scenarios for the foreign IP address comparison done by in_pcblookup.


The additional comparison of the foreign port numbers can be performed for the second line of Figure 22.18 because it is not possible to have a PCB with a nonwildcard foreign address and a foreign port number of 0. This restriction is enforced by connect, which we'll see shortly requires a nonwildcard foreign IP address and a nonzero foreign port. It is possible, however, and common, to have a wildcard local address with a nonzero local port. We saw this in Figures 22.10 and 22.13.



Check if wildcard match allowed


438-439

The flags argument can be set to INPLOOKUP_WILDCARD, which means a match containing wildcards is OK. If a match is found containing wildcards (wildcard is nonzero) and this flag was not specified by the caller, this PCB is ignored. When TCP and UDP call this function to demultiplex an incoming datagram, INPLOOKUP_WILDCARD is always set, since a wildcard match is OK. (Recall our examples using Figures 22.10 and 22.13.) But when this function is called as part of the connect system call, in order to verify that a socket pair is not already in use, the flags argument is set to 0.



Remember best match, return if exact match found


440-447

These statements remember the best match found so far. Again, the best match is considered the one with the fewest number of wildcard matches. If a match is found with one or two wildcards, that match is remembered and the loop continues. But if an exact match is found (wildcard is 0), the loop terminates, and a pointer to the PCB with that exact match is returned.



Example�Demultiplexing of Received TCP Segment


Figure 22.19 is from the TCP example we discussed with Figure 22.11. Assume in_pcblookup is demultiplexing a received datagram from 140.252.1.11, port 1500, destined for 140.252.1.29, port 23. Also assume that the order of the PCBs is the order of the rows in the figure. laddr is the destination IP address, lport is the destination TCP port, faddr is the source IP address, and fport is the source TCP port.



Figure 22.19. laddr = 140.252.1.29, lport = 23, faddr = 140.252.1.11, fport = 1500.


When the first row is compared to the incoming segment, wildcard is 1 (the foreign IP address), flags is set to INPLOOKUP_WILDCARD, so match is set to point to this PCB and matchwild is set to 1. The loop continues since an exact match has not been found yet. The next time around the loop, wildcard is 2 (the local and foreign IP addresses) and since this is greater than matchwild, the entry is not remembered, and the loop continues. The next time around the loop, wildcard is 0, which is less than matchwild (1), so this entry is remembered in match. The loop also terminates since an exact match has been found and the pointer to this PCB is returned to the caller.


If in_pcblookup were used by TCP and UDP only to demultiplex incoming datagrams, it could be simplified. First, there's no need to check whether the faddr or laddr arguments are wildcards, since these are the source and destination IP addresses from the received datagram. Also the flags argument could be removed, along with its corresponding test, since wildcard matches are always OK.


This section has covered the mechanics of the in_pcblookup function. We'll return to this function and discuss its meaning after seeing how it is called from the in_pcbbind and in_pcbconnect functions.





    Team-Fly
     

     
    Top
     


    No comments:

    Post a Comment