tcpip.c

Go to the documentation of this file.
00001 #include <stdint.h>
00002 #include <string.h>
00003 #include <errno.h>
00004 #include <byteswap.h>
00005 #include <gpxe/iobuf.h>
00006 #include <gpxe/tables.h>
00007 #include <gpxe/tcpip.h>
00008 
00009 /** @file
00010  *
00011  * Transport-network layer interface
00012  *
00013  * This file contains functions and utilities for the
00014  * TCP/IP transport-network layer interface
00015  */
00016 
00017 FILE_LICENCE ( GPL2_OR_LATER );
00018 
00019 /** Process a received TCP/IP packet
00020  *
00021  * @v iobuf             I/O buffer
00022  * @v tcpip_proto       Transport-layer protocol number
00023  * @v st_src            Partially-filled source address
00024  * @v st_dest           Partially-filled destination address
00025  * @v pshdr_csum        Pseudo-header checksum
00026  * @ret rc              Return status code
00027  *
00028  * This function expects a transport-layer segment from the network
00029  * layer.  The network layer should fill in as much as it can of the
00030  * source and destination addresses (i.e. it should fill in the
00031  * address family and the network-layer addresses, but leave the ports
00032  * and the rest of the structures as zero).
00033  */
00034 int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto, 
00035                struct sockaddr_tcpip *st_src,
00036                struct sockaddr_tcpip *st_dest,
00037                uint16_t pshdr_csum ) {
00038         struct tcpip_protocol *tcpip;
00039 
00040         /* Hand off packet to the appropriate transport-layer protocol */
00041         for_each_table_entry ( tcpip, TCPIP_PROTOCOLS ) {
00042                 if ( tcpip->tcpip_proto == tcpip_proto ) {
00043                         DBG ( "TCP/IP received %s packet\n", tcpip->name );
00044                         return tcpip->rx ( iobuf, st_src, st_dest, pshdr_csum );
00045                 }
00046         }
00047 
00048         DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
00049         free_iob ( iobuf );
00050         return -EPROTONOSUPPORT;
00051 }
00052 
00053 /** Transmit a TCP/IP packet
00054  *
00055  * @v iobuf             I/O buffer
00056  * @v tcpip_protocol    Transport-layer protocol
00057  * @v st_src            Source address, or NULL to use route default
00058  * @v st_dest           Destination address
00059  * @v netdev            Network device to use if no route found, or NULL
00060  * @v trans_csum        Transport-layer checksum to complete, or NULL
00061  * @ret rc              Return status code
00062  */
00063 int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
00064                struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
00065                struct net_device *netdev, uint16_t *trans_csum ) {
00066         struct tcpip_net_protocol *tcpip_net;
00067 
00068         /* Hand off packet to the appropriate network-layer protocol */
00069         for_each_table_entry ( tcpip_net, TCPIP_NET_PROTOCOLS ) {
00070                 if ( tcpip_net->sa_family == st_dest->st_family ) {
00071                         DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
00072                         return tcpip_net->tx ( iobuf, tcpip_protocol, st_src,
00073                                                st_dest, netdev, trans_csum );
00074                 }
00075         }
00076         
00077         DBG ( "Unrecognised TCP/IP address family %d\n", st_dest->st_family );
00078         free_iob ( iobuf );
00079         return -EAFNOSUPPORT;
00080 }
00081 
00082 /**
00083  * Calculate continued TCP/IP checkum
00084  *
00085  * @v partial           Checksum of already-summed data, in network byte order
00086  * @v data              Data buffer
00087  * @v len               Length of data buffer
00088  * @ret cksum           Updated checksum, in network byte order
00089  *
00090  * Calculates a TCP/IP-style 16-bit checksum over the data block.  The
00091  * checksum is returned in network byte order.
00092  *
00093  * This function may be used to add new data to an existing checksum.
00094  * The function assumes that both the old data and the new data start
00095  * on even byte offsets; if this is not the case then you will need to
00096  * byte-swap either the input partial checksum, the output checksum,
00097  * or both.  Deciding which to swap is left as an exercise for the
00098  * interested reader.
00099  */
00100 uint16_t tcpip_continue_chksum ( uint16_t partial, const void *data,
00101                                  size_t len ) {
00102         unsigned int cksum = ( ( ~partial ) & 0xffff );
00103         unsigned int value;
00104         unsigned int i;
00105         
00106         for ( i = 0 ; i < len ; i++ ) {
00107                 value = * ( ( uint8_t * ) data + i );
00108                 if ( i & 1 ) {
00109                         /* Odd bytes: swap on little-endian systems */
00110                         value = be16_to_cpu ( value );
00111                 } else {
00112                         /* Even bytes: swap on big-endian systems */
00113                         value = le16_to_cpu ( value );
00114                 }
00115                 cksum += value;
00116                 if ( cksum > 0xffff )
00117                         cksum -= 0xffff;
00118         }
00119         
00120         return ( ~cksum );
00121 }
00122 
00123 /**
00124  * Calculate TCP/IP checkum
00125  *
00126  * @v data              Data buffer
00127  * @v len               Length of data buffer
00128  * @ret cksum           Checksum, in network byte order
00129  *
00130  * Calculates a TCP/IP-style 16-bit checksum over the data block.  The
00131  * checksum is returned in network byte order.
00132  */
00133 uint16_t tcpip_chksum ( const void *data, size_t len ) {
00134         return tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, data, len );
00135 }

Generated on Tue Apr 6 20:01:11 2010 for gPXE by  doxygen 1.5.7.1