iPXE
Data Structures | Defines | Enumerations | Functions
tcpip.h File Reference

Transport-network layer interface. More...

#include <stdint.h>
#include <ipxe/socket.h>
#include <ipxe/in.h>
#include <ipxe/tables.h>
#include <bits/tcpip.h>

Go to the source code of this file.

Data Structures

struct  sockaddr_tcpip
 TCP/IP socket address. More...
struct  tcpip_protocol
 A transport-layer protocol of the TCP/IP stack (eg. More...
struct  tcpip_net_protocol
 A network-layer protocol of the TCP/IP stack (eg. More...

Defines

#define TCPIP_POSITIVE_ZERO_CSUM   0x0000
 Positive zero checksum value.
#define TCPIP_NEGATIVE_ZERO_CSUM   0xffff
 Negative zero checksum value.
#define TCPIP_EMPTY_CSUM   TCPIP_POSITIVE_ZERO_CSUM
 Empty checksum value.
#define TCPIP_PROTOCOLS   __table ( struct tcpip_protocol, "tcpip_protocols" )
 TCP/IP transport-layer protocol table.
#define __tcpip_protocol   __table_entry ( TCPIP_PROTOCOLS, 01 )
 Declare a TCP/IP transport-layer protocol.
#define TCPIP_NET_PROTOCOLS   __table ( struct tcpip_net_protocol, "tcpip_net_protocols" )
 TCP/IP network-layer protocol table.
#define __tcpip_net_protocol   __table_entry ( TCPIP_NET_PROTOCOLS, 01 )
 Declare a TCP/IP network-layer protocol.

Enumerations

enum  tcpip_st_flags { TCPIP_BIND_PRIVILEGED = 0x0400 }
 TCP/IP address flags. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
uint16_t generic_tcpip_continue_chksum (uint16_t partial, const void *data, size_t len)
 Calculate continued TCP/IP checkum.
int tcpip_rx (struct io_buffer *iobuf, struct net_device *netdev, uint8_t tcpip_proto, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum, struct ip_statistics *stats)
 Process a received TCP/IP packet.
int tcpip_tx (struct io_buffer *iobuf, struct tcpip_protocol *tcpip, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum)
 Transmit a TCP/IP packet.
struct tcpip_net_protocoltcpip_net_protocol (sa_family_t sa_family)
 Find TCP/IP network-layer protocol.
struct net_devicetcpip_netdev (struct sockaddr_tcpip *st_dest)
 Determine transmitting network device.
size_t tcpip_mtu (struct sockaddr_tcpip *st_dest)
 Determine maximum transmission unit.
uint16_t tcpip_chksum (const void *data, size_t len)
 Calculate TCP/IP checkum.
int tcpip_bind (struct sockaddr_tcpip *st_local, int(*available)(int port))
 Bind to local TCP/IP port.

Detailed Description

Transport-network layer interface.

Definition in file tcpip.h.


Define Documentation

#define TCPIP_POSITIVE_ZERO_CSUM   0x0000

Positive zero checksum value.

Definition at line 27 of file tcpip.h.

#define TCPIP_NEGATIVE_ZERO_CSUM   0xffff

Negative zero checksum value.

Definition at line 30 of file tcpip.h.

Empty checksum value.

All of our TCP/IP checksum algorithms will return only the positive representation of zero (0x0000) for a zero checksum over non-zero input data. This property arises since the end-around carry used to mimic one's complement addition using unsigned arithmetic prevents the running total from ever returning to 0x0000. The running total will therefore use only the negative representation of zero (0xffff). Since the return value is the one's complement negation of the running total (calculated by simply bit-inverting the running total), the return value will therefore use only the positive representation of zero (0x0000).

It is a very common misconception (found in many places such as RFC1624) that this is a property guaranteed by the underlying mathematics. It is not; the choice of which zero representation is used is merely an artifact of the software implementation of the checksum algorithm.

For consistency, we choose to use the positive representation of zero (0x0000) for the checksum of a zero-length block of data. This ensures that all of our TCP/IP checksum algorithms will return only the positive representation of zero (0x0000) for a zero checksum (regardless of the input data).

Definition at line 57 of file tcpip.h.

Referenced by ipv4_rx(), ipv6_rx(), tcpip_chksum(), tcpip_okx(), and tcpip_random_okx().

#define TCPIP_PROTOCOLS   __table ( struct tcpip_protocol, "tcpip_protocols" )

TCP/IP transport-layer protocol table.

Definition at line 178 of file tcpip.h.

Referenced by tcpip_rx().

Declare a TCP/IP transport-layer protocol.

Definition at line 181 of file tcpip.h.

#define TCPIP_NET_PROTOCOLS   __table ( struct tcpip_net_protocol, "tcpip_net_protocols" )

TCP/IP network-layer protocol table.

Definition at line 184 of file tcpip.h.

Referenced by tcpip_net_protocol().

Declare a TCP/IP network-layer protocol.

Definition at line 188 of file tcpip.h.


Enumeration Type Documentation

TCP/IP address flags.

Enumerator:
TCPIP_BIND_PRIVILEGED 

Bind to a privileged port (less than 1024)

This value is chosen as 1024 to optimise the calculations in tcpip_bind().

Definition at line 60 of file tcpip.h.

                    {
        /** Bind to a privileged port (less than 1024)
         *
         * This value is chosen as 1024 to optimise the calculations
         * in tcpip_bind().
         */
        TCPIP_BIND_PRIVILEGED = 0x0400,
};

Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
uint16_t generic_tcpip_continue_chksum ( uint16_t  partial,
const void *  data,
size_t  len 
)

Calculate continued TCP/IP checkum.

Parameters:
partialChecksum of already-summed data, in network byte order
dataData buffer
lenLength of data buffer
Return values:
cksumUpdated checksum, in network byte order

Calculates a TCP/IP-style 16-bit checksum over the data block. The checksum is returned in network byte order.

This function may be used to add new data to an existing checksum. The function assumes that both the old data and the new data start on even byte offsets; if this is not the case then you will need to byte-swap either the input partial checksum, the output checksum, or both. Deciding which to swap is left as an exercise for the interested reader.

Definition at line 170 of file tcpip.c.

References be16_to_cpu, le16_to_cpu, len, and value.

Referenced by tcpip_okx(), and tcpip_random_okx().

                                                                        {
        unsigned int cksum = ( ( ~partial ) & 0xffff );
        unsigned int value;
        unsigned int i;
        
        for ( i = 0 ; i < len ; i++ ) {
                value = * ( ( uint8_t * ) data + i );
                if ( i & 1 ) {
                        /* Odd bytes: swap on little-endian systems */
                        value = be16_to_cpu ( value );
                } else {
                        /* Even bytes: swap on big-endian systems */
                        value = le16_to_cpu ( value );
                }
                cksum += value;
                if ( cksum > 0xffff )
                        cksum -= 0xffff;
        }
        
        return ( ~cksum );
}
int tcpip_rx ( struct io_buffer iobuf,
struct net_device netdev,
uint8_t  tcpip_proto,
struct sockaddr_tcpip st_src,
struct sockaddr_tcpip st_dest,
uint16_t  pshdr_csum,
struct ip_statistics stats 
)

Process a received TCP/IP packet.

Parameters:
iobufI/O buffer
netdevNetwork device
tcpip_protoTransport-layer protocol number
st_srcPartially-filled source address
st_destPartially-filled destination address
pshdr_csumPseudo-header checksum
statsIP statistics
Return values:
rcReturn status code

This function expects a transport-layer segment from the network layer. The network layer should fill in as much as it can of the source and destination addresses (i.e. it should fill in the address family and the network-layer addresses, but leave the ports and the rest of the structures as zero).

Definition at line 40 of file tcpip.c.

References DBG, EPROTONOSUPPORT, for_each_table_entry, free_iob(), ip_statistics::in_delivers, ip_statistics::in_unknown_protos, tcpip_protocol::name, tcpip_protocol::rx, tcpip_protocol::tcpip_proto, and TCPIP_PROTOCOLS.

Referenced by ipv4_rx(), and ipv6_rx().

                                             {
        struct tcpip_protocol *tcpip;

        /* Hand off packet to the appropriate transport-layer protocol */
        for_each_table_entry ( tcpip, TCPIP_PROTOCOLS ) {
                if ( tcpip->tcpip_proto == tcpip_proto ) {
                        DBG ( "TCP/IP received %s packet\n", tcpip->name );
                        stats->in_delivers++;
                        return tcpip->rx ( iobuf, netdev, st_src, st_dest,
                                           pshdr_csum );
                }
        }

        DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
        stats->in_unknown_protos++;
        free_iob ( iobuf );
        return -EPROTONOSUPPORT;
}
int tcpip_tx ( struct io_buffer iobuf,
struct tcpip_protocol tcpip_protocol,
struct sockaddr_tcpip st_src,
struct sockaddr_tcpip st_dest,
struct net_device netdev,
uint16_t trans_csum 
)

Transmit a TCP/IP packet.

Parameters:
iobufI/O buffer
tcpip_protocolTransport-layer protocol
st_srcSource address, or NULL to use route default
st_destDestination address
netdevNetwork device to use if no route found, or NULL
trans_csumTransport-layer checksum to complete, or NULL
Return values:
rcReturn status code

Definition at line 91 of file tcpip.c.

References DBG, EAFNOSUPPORT, free_iob(), tcpip_net_protocol::name, sockaddr_tcpip::st_family, tcpip_net_protocol(), and tcpip_net_protocol::tx.

Referenced by icmp_tx_echo(), ndp_tx_ll_addr(), tcp_xmit_reset(), tcp_xmit_sack(), and udp_tx().

                                                                 {
        struct tcpip_net_protocol *tcpip_net;

        /* Hand off packet to the appropriate network-layer protocol */
        tcpip_net = tcpip_net_protocol ( st_dest->st_family );
        if ( tcpip_net ) {
                DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
                return tcpip_net->tx ( iobuf, tcpip_protocol, st_src, st_dest,
                                       netdev, trans_csum );
        }

        free_iob ( iobuf );
        return -EAFNOSUPPORT;
}
struct tcpip_net_protocol* tcpip_net_protocol ( sa_family_t  sa_family) [read]

Find TCP/IP network-layer protocol.

Parameters:
sa_familyAddress family
Return values:
tcpip_netTCP/IP network-layer protocol, or NULL if not found

Definition at line 68 of file tcpip.c.

References DBG, for_each_table_entry, NULL, tcpip_net_protocol::sa_family, and TCPIP_NET_PROTOCOLS.

Referenced by efi_pxe_install(), efi_pxe_start(), efi_pxe_udp_deliver(), tcpip_mtu(), tcpip_netdev(), and tcpip_tx().

                                                                         {
        struct tcpip_net_protocol *tcpip_net;

        for_each_table_entry ( tcpip_net, TCPIP_NET_PROTOCOLS ) {
                if ( tcpip_net->sa_family == sa_family )
                        return tcpip_net;
        }

        DBG ( "Unrecognised TCP/IP address family %d\n", sa_family );
        return NULL;
}
struct net_device* tcpip_netdev ( struct sockaddr_tcpip st_dest) [read]

Determine transmitting network device.

Parameters:
st_destDestination address
Return values:
netdevNetwork device, or NULL

Definition at line 114 of file tcpip.c.

References tcpip_net_protocol::netdev, NULL, sockaddr_tcpip::st_family, and tcpip_net_protocol().

Referenced by ibft_fill_target_nic_association(), and ibft_netdev_is_required().

                                                                    {
        struct tcpip_net_protocol *tcpip_net;

        /* Hand off to the appropriate network-layer protocol */
        tcpip_net = tcpip_net_protocol ( st_dest->st_family );
        if ( tcpip_net )
                return tcpip_net->netdev ( st_dest );

        return NULL;
}
size_t tcpip_mtu ( struct sockaddr_tcpip st_dest)

Determine maximum transmission unit.

Parameters:
st_destDestination address
Return values:
mtuMaximum transmission unit

Definition at line 131 of file tcpip.c.

References tcpip_net_protocol::header_len, mtu, net_device::mtu, netdev, tcpip_net_protocol::netdev, sockaddr_tcpip::st_family, and tcpip_net_protocol().

Referenced by tcp_open().

                                                    {
        struct tcpip_net_protocol *tcpip_net;
        struct net_device *netdev;
        size_t mtu;

        /* Find appropriate network-layer protocol */
        tcpip_net = tcpip_net_protocol ( st_dest->st_family );
        if ( ! tcpip_net )
                return 0;

        /* Find transmitting network device */
        netdev = tcpip_net->netdev ( st_dest );
        if ( ! netdev )
                return 0;

        /* Calculate MTU */
        mtu = ( netdev->mtu - tcpip_net->header_len );

        return mtu;
}
uint16_t tcpip_chksum ( const void *  data,
size_t  len 
)

Calculate TCP/IP checkum.

Parameters:
dataData buffer
lenLength of data buffer
Return values:
cksumChecksum, in network byte order

Calculates a TCP/IP-style 16-bit checksum over the data block. The checksum is returned in network byte order.

Definition at line 203 of file tcpip.c.

References tcpip_continue_chksum(), and TCPIP_EMPTY_CSUM.

Referenced by gdbudp_send(), icmp_tx_echo(), icmpv4_rx(), ipv4_rx(), ipv4_tx(), ndp_tx_ll_addr(), tcp_xmit_reset(), tcp_xmit_sack(), and udp_tx().

int tcpip_bind ( struct sockaddr_tcpip st_local,
int(*)(int port available 
)

Bind to local TCP/IP port.

Parameters:
st_localLocal TCP/IP socket address, or NULL
availableFunction to check port availability
Return values:
portLocal port number, or negative error

Definition at line 214 of file tcpip.c.

References EADDRINUSE, flags, ntohs, offset, random(), sockaddr_tcpip::st_flags, sockaddr_tcpip::st_port, and TCPIP_BIND_PRIVILEGED.

Referenced by ping_open(), tcp_open(), and udp_open_common().

                                                    {
        uint16_t flags = 0;
        uint16_t try_port = 0;
        uint16_t min_port;
        uint16_t max_port;
        unsigned int offset;
        unsigned int i;

        /* Extract parameters from local socket address */
        if ( st_local ) {
                flags = st_local->st_flags;
                try_port = ntohs ( st_local->st_port );
        }

        /* If an explicit port is specified, check its availability */
        if ( try_port )
                return available ( try_port );

        /* Otherwise, find an available port in the range [1,1023] or
         * [1025,65535] as appropriate.
         */
        min_port = ( ( ( ~flags ) & TCPIP_BIND_PRIVILEGED ) + 1 );
        max_port = ( ( flags & TCPIP_BIND_PRIVILEGED ) - 1 );
        offset = random();
        for ( i = 0 ; i <= max_port ; i++ ) {
                try_port = ( ( i + offset ) & max_port );
                if ( try_port < min_port )
                        continue;
                if ( available ( try_port ) < 0 )
                        continue;
                return try_port;
        }
        return -EADDRINUSE;
}