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 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include <stdint.h>
  2. #include <string.h>
  3. #include <errno.h>
  4. #include <byteswap.h>
  5. #include <ipxe/iobuf.h>
  6. #include <ipxe/tables.h>
  7. #include <ipxe/tcpip.h>
  8. /** @file
  9. *
  10. * Transport-network layer interface
  11. *
  12. * This file contains functions and utilities for the
  13. * TCP/IP transport-network layer interface
  14. */
  15. FILE_LICENCE ( GPL2_OR_LATER );
  16. /** Process a received TCP/IP packet
  17. *
  18. * @v iobuf I/O buffer
  19. * @v tcpip_proto Transport-layer protocol number
  20. * @v st_src Partially-filled source address
  21. * @v st_dest Partially-filled destination address
  22. * @v pshdr_csum Pseudo-header checksum
  23. * @ret rc Return status code
  24. *
  25. * This function expects a transport-layer segment from the network
  26. * layer. The network layer should fill in as much as it can of the
  27. * source and destination addresses (i.e. it should fill in the
  28. * address family and the network-layer addresses, but leave the ports
  29. * and the rest of the structures as zero).
  30. */
  31. int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto,
  32. struct sockaddr_tcpip *st_src,
  33. struct sockaddr_tcpip *st_dest,
  34. uint16_t pshdr_csum ) {
  35. struct tcpip_protocol *tcpip;
  36. /* Hand off packet to the appropriate transport-layer protocol */
  37. for_each_table_entry ( tcpip, TCPIP_PROTOCOLS ) {
  38. if ( tcpip->tcpip_proto == tcpip_proto ) {
  39. DBG ( "TCP/IP received %s packet\n", tcpip->name );
  40. return tcpip->rx ( iobuf, st_src, st_dest, pshdr_csum );
  41. }
  42. }
  43. DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
  44. free_iob ( iobuf );
  45. return -EPROTONOSUPPORT;
  46. }
  47. /** Transmit a TCP/IP packet
  48. *
  49. * @v iobuf I/O buffer
  50. * @v tcpip_protocol Transport-layer protocol
  51. * @v st_src Source address, or NULL to use route default
  52. * @v st_dest Destination address
  53. * @v netdev Network device to use if no route found, or NULL
  54. * @v trans_csum Transport-layer checksum to complete, or NULL
  55. * @ret rc Return status code
  56. */
  57. int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
  58. struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
  59. struct net_device *netdev, uint16_t *trans_csum ) {
  60. struct tcpip_net_protocol *tcpip_net;
  61. /* Hand off packet to the appropriate network-layer protocol */
  62. for_each_table_entry ( tcpip_net, TCPIP_NET_PROTOCOLS ) {
  63. if ( tcpip_net->sa_family == st_dest->st_family ) {
  64. DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
  65. return tcpip_net->tx ( iobuf, tcpip_protocol, st_src,
  66. st_dest, netdev, trans_csum );
  67. }
  68. }
  69. DBG ( "Unrecognised TCP/IP address family %d\n", st_dest->st_family );
  70. free_iob ( iobuf );
  71. return -EAFNOSUPPORT;
  72. }
  73. /**
  74. * Calculate continued TCP/IP checkum
  75. *
  76. * @v partial Checksum of already-summed data, in network byte order
  77. * @v data Data buffer
  78. * @v len Length of data buffer
  79. * @ret cksum Updated checksum, in network byte order
  80. *
  81. * Calculates a TCP/IP-style 16-bit checksum over the data block. The
  82. * checksum is returned in network byte order.
  83. *
  84. * This function may be used to add new data to an existing checksum.
  85. * The function assumes that both the old data and the new data start
  86. * on even byte offsets; if this is not the case then you will need to
  87. * byte-swap either the input partial checksum, the output checksum,
  88. * or both. Deciding which to swap is left as an exercise for the
  89. * interested reader.
  90. */
  91. uint16_t tcpip_continue_chksum ( uint16_t partial, const void *data,
  92. size_t len ) {
  93. unsigned int cksum = ( ( ~partial ) & 0xffff );
  94. unsigned int value;
  95. unsigned int i;
  96. for ( i = 0 ; i < len ; i++ ) {
  97. value = * ( ( uint8_t * ) data + i );
  98. if ( i & 1 ) {
  99. /* Odd bytes: swap on little-endian systems */
  100. value = be16_to_cpu ( value );
  101. } else {
  102. /* Even bytes: swap on big-endian systems */
  103. value = le16_to_cpu ( value );
  104. }
  105. cksum += value;
  106. if ( cksum > 0xffff )
  107. cksum -= 0xffff;
  108. }
  109. return ( ~cksum );
  110. }
  111. /**
  112. * Calculate TCP/IP checkum
  113. *
  114. * @v data Data buffer
  115. * @v len Length of data buffer
  116. * @ret cksum Checksum, in network byte order
  117. *
  118. * Calculates a TCP/IP-style 16-bit checksum over the data block. The
  119. * checksum is returned in network byte order.
  120. */
  121. uint16_t tcpip_chksum ( const void *data, size_t len ) {
  122. return tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, data, len );
  123. }