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

TCP/IP协议栈

开发平台:

Visual C++

  1. /* IP header conversion routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "ip.h"
  7. #include "internet.h"
  8. /* Convert IP header in host format to network mbuf
  9.  * If cflag != 0, take checksum from structure,
  10.  * otherwise compute it automatically.
  11.  */
  12. void
  13. htonip(
  14. struct ip *ip,
  15. struct mbuf **bpp,
  16. int cflag
  17. ){
  18. uint16 hdr_len;
  19. register uint8 *cp;
  20. uint16 fl_offs;
  21. if(bpp == NULL)
  22. return;
  23. hdr_len = IPLEN + ip->optlen;
  24. if(hdr_len > IPLEN + IP_MAXOPT)
  25. hdr_len = IPLEN + IP_MAXOPT;
  26. pushdown(bpp,NULL,hdr_len);
  27. cp = (*bpp)->data;
  28. *cp++ = (ip->version << 4) | (hdr_len >> 2);
  29. *cp++ = ip->tos;
  30. cp = put16(cp,ip->length);
  31. cp = put16(cp,ip->id);
  32. fl_offs = ip->offset >> 3;
  33. if(ip->flags.congest)
  34. fl_offs |= 0x8000;
  35. if(ip->flags.df)
  36. fl_offs |= 0x4000;
  37. if(ip->flags.mf)
  38. fl_offs |= 0x2000;
  39. cp = put16(cp,fl_offs);
  40. *cp++ = ip->ttl;
  41. *cp++ = ip->protocol;
  42. if(cflag){
  43. /* Use checksum from host structure */
  44. cp = put16(cp,ip->checksum);
  45. } else {
  46. /* Clear checksum for later recalculation */
  47. *cp++ = 0;
  48. *cp++ = 0;
  49. }
  50. cp = put32(cp,ip->source);
  51. cp = put32(cp,ip->dest);
  52. if(ip->optlen != 0)
  53. memcpy(cp,ip->options,min(ip->optlen,IP_MAXOPT));
  54. /* If requested, recompute checksum and insert into header */
  55. if(!cflag)
  56. put16(&(*bpp)->data[10],cksum(NULL,*bpp,hdr_len));
  57. }
  58. /* Extract an IP header from mbuf */
  59. int
  60. ntohip(
  61. struct ip *ip,
  62. struct mbuf **bpp
  63. ){
  64. int ihl;
  65. uint16 fl_offs;
  66. uint8 ipbuf[IPLEN];
  67. if(pullup(bpp,ipbuf,IPLEN) != IPLEN)
  68. return -1;
  69. ip->version = (ipbuf[0] >> 4) & 0xf;
  70. ip->tos = ipbuf[1];
  71. ip->length = get16(&ipbuf[2]);
  72. ip->id = get16(&ipbuf[4]);
  73. fl_offs = get16(&ipbuf[6]);
  74. ip->offset = (fl_offs & 0x1fff) << 3;
  75. ip->flags.mf = (fl_offs & 0x2000) ? 1 : 0;
  76. ip->flags.df = (fl_offs & 0x4000) ? 1 : 0;
  77. ip->flags.congest = (fl_offs & 0x8000) ? 1 : 0;
  78. ip->ttl = ipbuf[8];
  79. ip->protocol = ipbuf[9];
  80. ip->checksum = get16(&ipbuf[10]);
  81. ip->source = get32(&ipbuf[12]);
  82. ip->dest = get32(&ipbuf[16]);
  83. ihl = (ipbuf[0] & 0xf) << 2;
  84. if(ihl < IPLEN){
  85. /* Bogus packet; header is too short */
  86. ip->optlen = 0;
  87. return -1;
  88. }
  89. if ( (ip->optlen = ihl - IPLEN) != 0 ) {
  90. if ( pullup(bpp,ip->options,ip->optlen) < ip->optlen )
  91. return -1;
  92. }
  93. return ihl;
  94. }
  95. /* Perform end-around-carry adjustment */
  96. uint16
  97. eac(
  98. int32 sum /* Carries in high order 16 bits */
  99. ){
  100. register uint16 csum;
  101. while((csum = sum >> 16) != 0)
  102. sum = csum + (sum & 0xffffL);
  103. return (uint16) (sum & 0xffffl); /* Chops to 16 bits */
  104. }
  105. /* Checksum a mbuf chain, with optional pseudo-header */
  106. uint16
  107. cksum(
  108. struct pseudo_header *ph,
  109. struct mbuf *m,
  110. uint16 len
  111. ){
  112. register uint16 cnt, total;
  113. register int32 sum, csum;
  114. register uint8 *up;
  115. uint16 csum1;
  116. int swap = 0;
  117. sum = 0l;
  118. /* Sum pseudo-header, if present */
  119. if(ph != NULL){
  120. sum = hiword(ph->source);
  121. sum += loword(ph->source);
  122. sum += hiword(ph->dest);
  123. sum += loword(ph->dest);
  124. sum += ph->protocol;
  125. sum += ph->length;
  126. }
  127. /* Now do each mbuf on the chain */
  128. for(total = 0; m != NULL && total < len; m = m->next) {
  129. cnt = min(m->cnt, len - total);
  130. up = m->data;
  131. csum = 0;
  132. if(((long)up) & 1){
  133. /* Handle odd leading byte */
  134. if(swap)
  135. csum = *up++;
  136. else
  137. csum = (uint16)*up++ << 8;
  138. cnt--;
  139. swap = !swap;
  140. }
  141. if(cnt > 1){
  142. /* Have the primitive checksumming routine do most of
  143.  * the work. At this point, up is guaranteed to be on
  144.  * a short boundary
  145.  */
  146. csum1 = lcsum((unsigned short *)up, (uint16)(cnt >> 1));
  147. if(swap)
  148. csum1 = (csum1 << 8) | (csum1 >> 8);
  149. csum += csum1;
  150. }
  151. /* Handle odd trailing byte */
  152. if(cnt & 1){
  153. if(swap)
  154. csum += up[--cnt];
  155. else
  156. csum += (uint16)up[--cnt] << 8;
  157. swap = !swap;
  158. }
  159. sum += csum;
  160. total += m->cnt;
  161. }
  162. /* Do final end-around carry, complement and return */
  163. return (uint16)(~eac(sum) & 0xffff);
  164. }