20.2 Implementation

   


The module interface of the connection-tracking module is located in the file net/ipv4/netfilter/ip_conntrack_standalone.c. The file net/ipv4/netfilter/ip_conntrack_core.c contains the actual connection-tracking functionality.

20.2.1 Basic Structure

The connection-tracking module hooks itself into the netfilter hooks NF_IP_PRE_ROUTING and NF_IP_LOCAL_OUT (see Section 19.3.1 and Figure 20-1) with very high priority (the NF_IP_PRI_CONNTRACK is set to ?00 in <linux/netfilter_ipv4.h>). This means that each incoming packet is first passed to the connection-tracking module. Subsequently, other modules also hooked into these hooks, but with lower priority, get their turns.

Figure 20-1. Netfilter hooks used by the connection-tracking module.

graphics/20fig01.gif


20.2.2 Connection Entries

struct ip_conntrack

linux/netfilter_ipv4/ip_conntrack.h


A connection entry is represented in the Linux kernel by an ip_conntrack structure, consisting of the following fields:

  • A structure of the type nf_conntrack (defined in <linux/skbuff.h>), which includes a reference counter (use) that counts the number of open references to this connection entry.

  • Two tuples for forward and reverse direction (tuplehash[0], tuplehash[1]), consisting of address and protocol information, which can be used to reference this entry.

  • A status field (status), containing a bit vector with the following bits:

    • IPS_EXPECTED: The connection was expected.

    • IPS_SEEN_REPLY: Packets have already occurred in both directions.

    • IPS_ASSURED: The connection entry should never be deleted prematurely, not even when the timeout expires.

  • A pointer (timeout) to a function that is invoked as soon as the timeout of this connection expires (i.e., when this connection has not been used over a lengthy period of time).

  • A data structure of the type ip_conntrack_expect, which can be used to allocate expected connections (e.g., FTP data connections after a command was sent over the control connection) to existing connections (in this case to the control connection).

  • Several structures of the type nf_ct_info, each belonging to a specific state. A pointer to the entry that matches an IP packet is entered in the nfct field of the pertaining sk_buff structure. The enumeration type ip_conntrack_info (defined in <linux/netfilter_ipv4/ip_conntrack.h>), which can take any of the following values, is used as index in the table that contains the nf_ct_info structures:

    • IP_CT_ESTABLISHED: The packet belongs to a fully established connection.

    • IP_CT_RELATED: The packet belongs to a new connection, which, however, refers to an existing connection (i.e., an expected connection).

    • IP_CT_NEW: The packet belongs to a new connection.

    • IP_CT_IS_REPLY: The packet belongs to the reverse direction of a connection.

  • A pointer to an optional helper module to extend the connection-tracking functionality. (See Section 20.2.4.)

struct ip_conntrack_tuple_hash

linux/netfilter_ipv4/ip_conntrack_tuple.h


Connection entries are managed in a hash table, where a linked list is used to resolve collisions. An entry in this hash table is of the type ip_conntrack_tuple_hash and contains a reverse pointer to the ip_conntrack structure of that connection, in addition to the actual address information (tuple) (i.e., source and destination addresses) and protocol-specific information (e.g., port numbers). As is shown in Figure 20-2, this pointer is required to access the connection status or to check for whether the entry represents a tuple for the forward or reverse direction of a connection.

Figure 20-2. Data structures of the connection-tracking module.

graphics/20fig02.gif


struct ip_conntrack_tuple

linux/netfilter_ipv4/ip_conntrack_tuple.h


An ip_conntrack_tuple is divided into a manipulable part, for the source address and perhaps the source port (ip_conntrack_manip), and a nonmanipulable part for destination address, protocol, and perhaps destination port. This division facilitates the use of connection entries by the NAT module.

20.2.3 Transport Protocols

struct ip_conntrack_protocol

linux/netfilter_ipv4/ip_conntrack_protocol.h


To enable use of different transport protocols, there is a global list with these protocols (protocol_list). A protocol is represented by a structure of the type ip_conntrack_protocol. The two functions ip_conntrack_protocol_register() and ip_conntrack_protocol_unregister() are used to add a protocol to or remove one from the list of supported protocols in the form of modules at runtime. Notice that, when you delete a protocol from the list, all connections currently using this protocol are also deleted.

To support a specific protocol, such a module has to contain the following functions:

  • Functions to output specific details about a connection in clear text (used by the proc file system).

  • Helper functions to invert tuples (i.e., to swap source and destination addresses) and to extract a tuple from an sk_buff structure.

  • Its own protocol-specific processing functions (e.g., functions to track the current state of the TCP protocol automaton, in the case of the TCP protocol).

  • Update functions for the timeout timer to ensure that a connection entry can be deleted, if it hasn't been used over a lengthy period of time.

20.2.4 Helper Modules

struct ip_conntrack_helper

linux/netfilter_ipv4/ip_conntrack_helper.h


The so-called helper modules provide an interface to extend the connection-tracking functionality. The functions ip_conntrack_helper_register() and ip_conntrack_helper_unregister() are used to add or remove a structure of the type ip_conntrack_helper to or from a linked list (helpers). Each packet that traverses one of the connection-tracking hooks is passed to each of the registered helper modules.

This enables us to support active FTP, where the associated helper module, ip_conntrack_ftp.o, updates the list of expected connections as soon as it detects a GET or PUT command while listening to the control connection. This means that it can assign data connections arriving from the outside to existing control connections.

20.2.5 Global Variables

The following global variables are important for the connection-tracking functionality:

  • ip_conntrack_hash, the hash tables with all connection entries see Section 20.2.2 for details;

  • expect_list, the list of expected connections. A connection is expected, for example, when a file transfer is started over an FTP control connection. This functionality is currently used by the FTP protocol only;

  • protocol_list, the list of registered transport protocols. TCP, UDP, ICMP, and a generic transport protocol module with minimum functionality, which is used when no matching protocol is found, are currently implemented;

  • helpers, the list of registered helper modules see Section 20.2.4.

20.2.6 Functions

print_tuple()

net/ipv4/netfilter/ip_conntrack_standalone.c


This function is invoked by print_conntrack() and outputs a single tuple for a connection (forward and reverse directions) in text form:

src=129.13.65.4 dst=168.42.17.1 sport=8080 dport=80

print_expect()

net/ipv4/netfilter/ip_conntrack_standalone.c


This function outputs a single tuple from the list of expected connections in text form:

EXPECTING: proto=23 src=129.13.65.4 dst=168.42.17.1 sport=8080 dport=80

print_conntrack()

net/ipv4/netfilter/ip_conntrack_standalone.c


This function outputs the connection entry for an entire connection (forward and reverse directions) in text form. In addition to the two tuples, this includes their status and the states of their timeout timers.

conntrack_iterate()

net/ipv4/netfilter/ip_conntrack_standalone.c


This is a helper function used to walk through all connections; it is invoked by list_conntracks().

list_conntracks()

net/ipv4/netfilter/ip_conntrack_standalone.c


This function outputs the connection entries of all connections, both those currently active and those expected. It is required to generate an entry for the proc file system.

init(), fini(), init_or_cleanup()

net/ipv4/netfilter/ip_conntrack_standalone.c


The init() and fini() functions are invoked to initialize or remove the connection-tracking module, and they, in turn, invoke the function init_or_cleanup() with the parameter 1 (initialize) or 0 (remove).

During the initialization, the actual connection-tracking functionality is initialized first by the calling of ip_conntrack_init(). Subsequently, the entry in the proc file system is generated, and the functions ip_conntrack_in() and ip_conntrack_local() are hooked into the appropriate netfilter hooks. Inversely, these functions are unhooked when the module is removed, the entry is deleted from the proc file system, and, finally, the function ip_conntrack_cleanup() is invoked.

ip_conntrack_init()

net/ipv4/netfilter/ip_conntrack_core.c


This is the initialization routine for the actual connection-tracking functionality. It adds the three standard protocols TCP, UDP, and ICMP to the protocol list and initializes the ip_conntrack_hash hash table.

ip_conntrack_clean.up()

net/ipv4/netfilter/ip_conntrack_core.c


This function prepares for a removal of the connection-tracking module. More specifically, a locking mechanism is used to ensure that all IP packets currently handled are properly completed. Subsequently, a few reserved memory locations are released.

hash_conntrack()

net/ipv4/netfilter/ip_conntrack_core.c


This helper function computes the hash value for a data structure of the type ip_conntrack_tuple.

get_tuple()

net/ipv4/netfilter/ip_conntrack_core.c


This function uses the protocol data passed from an IP packet to create a matching data structure of the type ip_conntrack_tuple. First, the IP source and destination addresses and the transport protocol are taken, and then the pkt_to_tuple function of the matching transport protocol module is invoked.

invert_tuple(), invert_tuplepr()

net/ipv4/netfilter/ip_conntrack_core.c


These functions invert an ip_conntrack_tuple structure by swapping the IP source and destination addresses. In addition, the function invert_tuple() of the matching transport protocol module is invoked for example, to swap the source and destination ports for TCP or UDP.

For invert_tuple(), a pointer to the ip_conntrack_protocol structure of the transport protocol has to be passed as parameter; invert_tuplepr() determines this itself from the passed ip_conntrack_tuple structure.

ip_conntrack_alter_reply()

net/ipv4/netfilter/ip_conntrack_core.c


This function replaces the tuple in a connection entry for the reverse direction by the value passed in newreply.

ip_conntrack_find_get()

net/ipv4/netfilter/ip_conntrack_core.c


This function uses the __ip_conntrack_find() function to search the ip_conntrack_hash hash table for a connection entry matching an ip_conntrack_tuple structure, where the parameter ignored_conntrack can be used to exclude a specific connection from the search explicitly. If the entry exists, then it is returned, and the ct_general. use reference counter is incremented by one. Otherwise, the function returns NULL.

ip_conntrack_get()

net/ipv4/netfilter/ip_conntrack_core.c


This function gets the connection entry and the connection status matching a passed sk_buff structure. The information required are simply extracted from the nfct field in the sk_buff structure.

ip_conntrack_put()

net/ipv4/netfilter/ip_conntrack_core.c


This function decrements the reference counter of a connection entry by one. For this purpose, it invokes the inline function nf_conntrack_put() defined in <linux/skbuff.h>, which uses atomic_dec_and_test() to decrement the reference counter. If this action causes the counter to reach 0 (i.e., there are no more references to this connection), then the function pointer destroy() is invoked to delete this connection entry. This pointer normally points to the function destroy_conntrack().

resolve_normal_ct()

net/ipv4/netfilter/ip_conntrack_core.c


This function tries to find a connection entry matching a passed sk_buff structure or creates such an entry, if it doesn't exist. First, it uses get_tuple() to create a structure of the type ip_conntrack_tuple from the packet's protocol data. Next, ip_conntrack_find_get() is used to find a matching connection entry. If no matching tuple is found, then init_conntrack() is invoked to create a new connection entry. Finally, the connection entry status is determined, and this status is used to set the nfct field of the passed sk_buff structure.

init_conntrack()

net/ipv4/netfilter/ip_conntrack_core.c


This function creates a new connection entry. First, it creates a structure of the type ip_conntrack. This structure consists of the passed tuple for the forward direction and its inversion (created by invert_tuple) for the reverse direction. Next, atomic_set() sets the reference counter ct_general .use to value 1. The only reference that exists initially is owned by the timeout timer, which is also initialized, and its timeout function pointer is set to the function death_by_timeout(). Previously, the relevant protocol module was initialized by calling its new() function. The function pointer ct_general.destroy(), which is invoked to delete a connection entry, is set to the function destroy_conntrack(). In addition, a helper is entered, if one was registered for the protocol used.

As soon as all data structures have been initialized, the next step checks on whether the connection to be entered was expected (i.e., whether it exists in the expect_list). If so, it is deleted from this list and set to the IPS_EXPECTED status.

ip_conntrack_in()

net/ipv4/netfilter/ip_conntrack_core.c


This function is hooked into the netfilter hook NF_IP_PRE_ROUTING; it is invoked for each packet arriving from the outside. It is also used by ip_conntrack_local(), because the only difference is in how fragmented IP packets are handled.

IP packets have to be defragmented before they can be assigned to a connection; fragments that have already arrived are collected by the function ip_ct_gather_frags(), which, in turn, uses the ip_defrag() function. When the last fragment of a fragmented packet is received, or if the packet was not fragmented, then an attempt is made to assign the packet to a connection.

First, find_proto() is used to determine the connection-tracking module for the transport protocol used. Next, the packet is checked to see whether it is an ICMP packet. If so, it is first passed to the function icmp_error_track(). If successful, this function returns one, and the packet is accepted by returning NF_ACCEPT.

In contrast, if icmp_error_track() returns null, the packet is further handled like any other packet. resolve_normal_ct() chooses the correct connection entry (or creates one, if none exists). Subsequently, the packet() function of the associated transport protocol module is invoked, and then the help() functions of all registered helper modules are invoked. If one of these functions fails, then nf_conntrack_put() releases this connection entry.

ip_conntrack_local()

net/ipv4/netfilter/ip_conntrack_standalone.c


This function is hooked into the netfilter hook NF_IP_LOCAL_OUT; accordingly, it is invoked for each IP packet originating from a local process. The only difference from how incoming packets are handled in ip_conntrack_in() is that fragmented packets are not handled by the connection-tracking module. All other packets are simply passed to ip_conntrack_in().

icmp_error_track()

net/ipv4/netfilter/ip_conntrack_core.c


This function serves to handle ICMP packets. First, some consistency checks are done with regard to the length field, the ICMP message type, and the ICMP checksum. More detailed handling is done for the following ICMP message types, each of which refers to a specific IP packet one where the payload field in the header contains the ICMP message (described in Section 21.1.4):

 ICMP_DEST_UNREACH ICMP_SOURCE_QUENCH ICMP_TIME_EXCEEDED ICMP_PARAMETERPROB ICMP_REDIRECT

ip_conntrack_find_get() finds a connection entry for the original packet header, which is also sent by this function, where the function invert_tuple() is used first, because the packet's source and destination addresses have to be swapped. If the function finds the entry, then a pointer to the appropriate ct_info structure is entered in the nfct field of the passed sk_buff structure.

destroy_conntrack()

net/ipv4/netfilter/ip_conntrack_core.c


Normally, this function is invoked over the function pointer ct_general.destroy() in the ip_conntrack structure to delete a connection entry. If this entry is linked to a "master" entry, then its reference counter is decremented by nf_conntrack_put(). Subsequently, a cleanup function hooked into the function pointer ip_conntrack_destroyed() is invoked, if present. Finally, atomic_dec() decrements the counter ip_conntrack_count to the number of existing connection entries.

death_by_timeout()

net/ipv4/netfilter/ip_conntrack_core.c


This function is invoked as soon as the timeout timer for a connection expires. Initially, clean_from_lists() (also defined in net/ipv4/netfilter/ip_conntrack_core.c) removes the connection entry from the list of active connections. Subsequently, ip_conntrack_put() decrements the reference counter. This deletes the connection, if there are no other references.

ip_conntrack_protocol_register()

net/ipv4/netfilter/ip_conntrack_standalone.c


This function registers a module for a transport protocol. The protocol is added to the protocol_list, if it is not yet present.

ip_conntrack_protocol_unregister()

net/ipv4/netfilter/ip_conntrack_standalone.c


This function unregisters a module for a transport protocol; it is currently (in Linux Version 2.4.8) still empty.

find_proto()

net/ipv4/netfilter/ip_conntrack_core.c


This function searches the protocol_list for a protocol and returns the appropriate entry, if successful. If the function doesn't find a matching entry, then the generic protocol is returned. First, READ_LOCK locks the management data of the connection-tracking module for reading, before the helper function __find_proto() is invoked for the actual search.

ip_conntrack_helper_register()

net/ipv4/netfilter/ip_conntrack_core.c


This function registers a helper module by adding it to the helpers list, if note is not yet present.

ip_conntrack_helper_unregister()

net/ipv4/netfilter/ip_conntrack_core.c


This function unregisters a helper module by deleting it from the helpers list. For this purpose, it searches all connection entries that point to this helper module. Subsequently, the function unhelp() sets the helper pointer for each such connection to NULL. If a connection occurs in the expect_list, then this instance is deleted.

Currently, the most important application for connection tracking and the reason why connection tracking was initially developed is the so-called network address translation (NAT), which will be discussed in the next chapter.


       


    Linux Network Architecture
    Linux Network Architecture
    ISBN: 131777203
    EAN: N/A
    Year: 2004
    Pages: 187

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net