You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tcpip.c 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <byteswap.h>
  6. #include <ipxe/iobuf.h>
  7. #include <ipxe/tables.h>
  8. #include <ipxe/ipstat.h>
  9. #include <ipxe/tcpip.h>
  10. /** @file
  11. *
  12. * Transport-network layer interface
  13. *
  14. * This file contains functions and utilities for the
  15. * TCP/IP transport-network layer interface
  16. */
  17. FILE_LICENCE ( GPL2_OR_LATER );
  18. /** Process a received TCP/IP packet
  19. *
  20. * @v iobuf I/O buffer
  21. * @v netdev Network device
  22. * @v tcpip_proto Transport-layer protocol number
  23. * @v st_src Partially-filled source address
  24. * @v st_dest Partially-filled destination address
  25. * @v pshdr_csum Pseudo-header checksum
  26. * @v stats IP statistics
  27. * @ret rc Return status code
  28. *
  29. * This function expects a transport-layer segment from the network
  30. * layer. The network layer should fill in as much as it can of the
  31. * source and destination addresses (i.e. it should fill in the
  32. * address family and the network-layer addresses, but leave the ports
  33. * and the rest of the structures as zero).
  34. */
  35. int tcpip_rx ( struct io_buffer *iobuf, struct net_device *netdev,
  36. uint8_t tcpip_proto, struct sockaddr_tcpip *st_src,
  37. struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum,
  38. struct ip_statistics *stats ) {
  39. struct tcpip_protocol *tcpip;
  40. /* Hand off packet to the appropriate transport-layer protocol */
  41. for_each_table_entry ( tcpip, TCPIP_PROTOCOLS ) {
  42. if ( tcpip->tcpip_proto == tcpip_proto ) {
  43. DBG ( "TCP/IP received %s packet\n", tcpip->name );
  44. stats->in_delivers++;
  45. return tcpip->rx ( iobuf, netdev, st_src, st_dest,
  46. pshdr_csum );
  47. }
  48. }
  49. DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
  50. stats->in_unknown_protos++;
  51. free_iob ( iobuf );
  52. return -EPROTONOSUPPORT;
  53. }
  54. /** Transmit a TCP/IP packet
  55. *
  56. * @v iobuf I/O buffer
  57. * @v tcpip_protocol Transport-layer protocol
  58. * @v st_src Source address, or NULL to use route default
  59. * @v st_dest Destination address
  60. * @v netdev Network device to use if no route found, or NULL
  61. * @v trans_csum Transport-layer checksum to complete, or NULL
  62. * @ret rc Return status code
  63. */
  64. int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
  65. struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
  66. struct net_device *netdev, uint16_t *trans_csum ) {
  67. struct tcpip_net_protocol *tcpip_net;
  68. /* Hand off packet to the appropriate network-layer protocol */
  69. for_each_table_entry ( tcpip_net, TCPIP_NET_PROTOCOLS ) {
  70. if ( tcpip_net->sa_family == st_dest->st_family ) {
  71. DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
  72. return tcpip_net->tx ( iobuf, tcpip_protocol, st_src,
  73. st_dest, netdev, trans_csum );
  74. }
  75. }
  76. DBG ( "Unrecognised TCP/IP address family %d\n", st_dest->st_family );
  77. free_iob ( iobuf );
  78. return -EAFNOSUPPORT;
  79. }
  80. /**
  81. * Calculate continued TCP/IP checkum
  82. *
  83. * @v partial Checksum of already-summed data, in network byte order
  84. * @v data Data buffer
  85. * @v len Length of data buffer
  86. * @ret cksum Updated checksum, in network byte order
  87. *
  88. * Calculates a TCP/IP-style 16-bit checksum over the data block. The
  89. * checksum is returned in network byte order.
  90. *
  91. * This function may be used to add new data to an existing checksum.
  92. * The function assumes that both the old data and the new data start
  93. * on even byte offsets; if this is not the case then you will need to
  94. * byte-swap either the input partial checksum, the output checksum,
  95. * or both. Deciding which to swap is left as an exercise for the
  96. * interested reader.
  97. */
  98. uint16_t generic_tcpip_continue_chksum ( uint16_t partial,
  99. const void *data, size_t len ) {
  100. unsigned int cksum = ( ( ~partial ) & 0xffff );
  101. unsigned int value;
  102. unsigned int i;
  103. for ( i = 0 ; i < len ; i++ ) {
  104. value = * ( ( uint8_t * ) data + i );
  105. if ( i & 1 ) {
  106. /* Odd bytes: swap on little-endian systems */
  107. value = be16_to_cpu ( value );
  108. } else {
  109. /* Even bytes: swap on big-endian systems */
  110. value = le16_to_cpu ( value );
  111. }
  112. cksum += value;
  113. if ( cksum > 0xffff )
  114. cksum -= 0xffff;
  115. }
  116. return ( ~cksum );
  117. }
  118. /**
  119. * Calculate TCP/IP checkum
  120. *
  121. * @v data Data buffer
  122. * @v len Length of data buffer
  123. * @ret cksum Checksum, in network byte order
  124. *
  125. * Calculates a TCP/IP-style 16-bit checksum over the data block. The
  126. * checksum is returned in network byte order.
  127. */
  128. uint16_t tcpip_chksum ( const void *data, size_t len ) {
  129. return tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, data, len );
  130. }
  131. /**
  132. * Bind to local TCP/IP port
  133. *
  134. * @v st_local Local TCP/IP socket address, or NULL
  135. * @v available Function to check port availability
  136. * @ret port Local port number, or negative error
  137. */
  138. int tcpip_bind ( struct sockaddr_tcpip *st_local,
  139. int ( * available ) ( int port ) ) {
  140. uint16_t flags = 0;
  141. uint16_t try_port = 0;
  142. uint16_t min_port;
  143. uint16_t max_port;
  144. unsigned int offset;
  145. unsigned int i;
  146. /* Extract parameters from local socket address */
  147. if ( st_local ) {
  148. flags = st_local->st_flags;
  149. try_port = ntohs ( st_local->st_port );
  150. }
  151. /* If an explicit port is specified, check its availability */
  152. if ( try_port )
  153. return available ( try_port );
  154. /* Otherwise, find an available port in the range [1,1023] or
  155. * [1025,65535] as appropriate.
  156. */
  157. min_port = ( ( ( ! flags ) & TCPIP_BIND_PRIVILEGED ) + 1 );
  158. max_port = ( ( flags & TCPIP_BIND_PRIVILEGED ) - 1 );
  159. offset = random();
  160. for ( i = 0 ; i <= max_port ; i++ ) {
  161. try_port = ( ( i + offset ) & max_port );
  162. if ( try_port < min_port )
  163. continue;
  164. if ( available ( try_port ) < 0 )
  165. continue;
  166. return try_port;
  167. }
  168. return -EADDRINUSE;
  169. }