Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

tcpip.c 4.1KB

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