tcphdr.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:4k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* TCP header conversion routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "tcp.h"
  7. #include "ip.h"
  8. #include "internet.h"
  9. /* Convert TCP header in host format into mbuf ready for transmission,
  10.  * link in data (if any).
  11.  *
  12.  * If checksum field is zero, recompute it, otherwise take the value
  13.  * in the host header.
  14.  */
  15. void
  16. htontcp(
  17. struct tcp *tcph,
  18. struct mbuf **bpp, /* Data in, packet out */
  19. int32 ipsrc, /* For computing header checksum */
  20. int32 ipdest
  21. ){
  22. uint16 hdrlen;
  23. register uint8 *cp;
  24. if(bpp == NULL)
  25. return;
  26. hdrlen = TCPLEN;
  27. if(tcph->flags.mss)
  28. hdrlen += MSS_LENGTH;
  29. if(tcph->flags.tstamp)
  30. hdrlen += TSTAMP_LENGTH;
  31. if(tcph->flags.wscale)
  32. hdrlen += WSCALE_LENGTH;
  33. hdrlen = (hdrlen + 3) & 0xfc; /* Round up to multiple of 4 */
  34. pushdown(bpp,NULL,hdrlen);
  35. cp = (*bpp)->data;
  36. memset(cp,0,hdrlen);
  37. cp = put16(cp,tcph->source);
  38. cp = put16(cp,tcph->dest);
  39. cp = put32(cp,tcph->seq);
  40. cp = put32(cp,tcph->ack);
  41. *cp++ = hdrlen << 2; /* Offset field */
  42. *cp = 0;
  43. if(tcph->flags.congest)
  44. *cp |= 64;
  45. if(tcph->flags.urg)
  46. *cp |= 32;
  47. if(tcph->flags.ack)
  48. *cp |= 16;
  49. if(tcph->flags.psh)
  50. *cp |= 8;
  51. if(tcph->flags.rst)
  52. *cp |= 4;
  53. if(tcph->flags.syn)
  54. *cp |= 2;
  55. if(tcph->flags.fin)
  56. *cp |= 1;
  57. cp++;
  58. cp = put16(cp,tcph->wnd);
  59. cp = put16(cp,tcph->checksum);
  60. cp = put16(cp,tcph->up);
  61. /* Write options, if any */
  62. if(tcph->flags.mss){
  63. *cp++ = MSS_KIND;
  64. *cp++ = MSS_LENGTH;
  65. cp = put16(cp,tcph->mss);
  66. }
  67. if(tcph->flags.tstamp){
  68. *cp++ = TSTAMP_KIND;
  69. *cp++ = TSTAMP_LENGTH;
  70. cp = put32(cp,tcph->tsval);
  71. cp = put32(cp,tcph->tsecr);
  72. }
  73. if(tcph->flags.wscale){
  74. *cp++ = WSCALE_KIND;
  75. *cp++ = WSCALE_LENGTH;
  76. *cp++ = tcph->wsopt;
  77. }
  78. if(tcph->checksum == 0){
  79. /* Recompute header checksum */
  80. struct pseudo_header ph;
  81. ph.source = ipsrc;
  82. ph.dest = ipdest;
  83. ph.protocol = TCP_PTCL;
  84. ph.length = len_p(*bpp);
  85. put16(&(*bpp)->data[16],cksum(&ph,*bpp,ph.length));
  86. }
  87. }
  88. /* Pull TCP header off mbuf */
  89. int
  90. ntohtcp(
  91. struct tcp *tcph,
  92. struct mbuf **bpp
  93. ){
  94. int hdrlen,i,optlen,kind;
  95. register int flags;
  96. uint8 hdrbuf[TCPLEN],*cp;
  97. uint8 options[TCP_MAXOPT];
  98. memset(tcph,0,sizeof(struct tcp));
  99. i = pullup(bpp,hdrbuf,TCPLEN);
  100. /* Note that the results will be garbage if the header is too short.
  101.  * We don't check for this because returned ICMP messages will be
  102.  * truncated, and we at least want to get the port numbers.
  103.  */
  104. tcph->source = get16(&hdrbuf[0]);
  105. tcph->dest = get16(&hdrbuf[2]);
  106. tcph->seq = get32(&hdrbuf[4]);
  107. tcph->ack = get32(&hdrbuf[8]);
  108. hdrlen = (hdrbuf[12] & 0xf0) >> 2;
  109. flags = hdrbuf[13];
  110. tcph->flags.congest = (flags & 64) ? 1 : 0;
  111. tcph->flags.urg = (flags & 32) ? 1 : 0;
  112. tcph->flags.ack = (flags & 16) ? 1 : 0;
  113. tcph->flags.psh = (flags & 8) ? 1 : 0;
  114. tcph->flags.rst = (flags & 4) ? 1 : 0;
  115. tcph->flags.syn = (flags & 2) ? 1 : 0;
  116. tcph->flags.fin = (flags & 1) ? 1 : 0;
  117. tcph->wnd = get16(&hdrbuf[14]);
  118. tcph->checksum = get16(&hdrbuf[16]);
  119. tcph->up = get16(&hdrbuf[18]);
  120. optlen = hdrlen - TCPLEN;
  121. /* Check for option field */
  122. if(i < TCPLEN || hdrlen < TCPLEN)
  123. return -1; /* Header smaller than legal minimum */
  124. if(optlen == 0)
  125. return (int)hdrlen; /* No options, all done */
  126. if(optlen > len_p(*bpp)){
  127. /* Remainder too short for options length specified */
  128. return -1;
  129. }
  130. pullup(bpp,options,optlen); /* "Can't fail" */
  131. /* Process options */
  132. for(cp=options,i=optlen; i > 0;){
  133. kind = *cp++;
  134. i--;
  135. /* Process single-byte options */
  136. switch(kind){
  137. case EOL_KIND:
  138. return (int)hdrlen; /* End of options list */
  139. case NOOP_KIND:
  140. continue; /* Go look for next option */
  141. }
  142. /* All other options have a length field */
  143. optlen = *cp++;
  144. /* Process valid multi-byte options */
  145. switch(kind){
  146. case MSS_KIND:
  147. if(optlen == MSS_LENGTH){
  148. tcph->mss = get16(cp);
  149. tcph->flags.mss = 1;
  150. }
  151. break;
  152. case WSCALE_KIND:
  153. if(optlen == WSCALE_LENGTH){
  154. tcph->wsopt = *cp;
  155. tcph->flags.wscale = 1;
  156. }
  157. break;
  158. case TSTAMP_KIND:
  159. if(optlen == TSTAMP_LENGTH){
  160. tcph->tsval = get32(cp);
  161. tcph->tsecr = get32(cp+4);
  162. tcph->flags.tstamp = 1;
  163. }
  164. break;
  165. }
  166. optlen = max(2,optlen); /* Enforce legal minimum */
  167. i -= optlen;
  168. cp += optlen - 2;
  169. }
  170. return (int)hdrlen;
  171. }