Changeset 10966 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Jul 30, 2008 2:40:20 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/checksum/ipv4.cpp
r10964 r10966 40 40 * 41 41 * @returns Checksum. 42 * @param pIpHdr Pointer to the IPv4 header to checksum . Assumes43 * the caller already checked the minimum size requirement.42 * @param pIpHdr Pointer to the IPv4 header to checksum, network endian (big). 43 * Assumes the caller already checked the minimum size requirement. 44 44 */ 45 45 RTDECL(uint16_t) RTNetIPv4Checksum(PCRTNETIPV4 pIpHdr) 46 46 { 47 47 uint16_t const *paw = (uint16_t const *)pIpHdr; 48 int32_t iSum = paw[0] /* ip_hl */49 + paw[1] /* ip_len */50 + paw[2] /* ip_id */51 + paw[3] /* ip_off */52 + paw[4] /* ip_ttl */53 /*+ paw[5] == 0 */ /* ip_sum */54 + paw[6] /* ip_src */55 + paw[7] /* ip_src:16 */56 + paw[8] /* ip_dst */57 + paw[9]; /* ip_dst:16 */48 int32_t iSum = paw[0] /* ip_hl */ 49 + paw[1] /* ip_len */ 50 + paw[2] /* ip_id */ 51 + paw[3] /* ip_off */ 52 + paw[4] /* ip_ttl */ 53 /*+ paw[5] == 0 */ /* ip_sum */ 54 + paw[6] /* ip_src */ 55 + paw[7] /* ip_src:16 */ 56 + paw[8] /* ip_dst */ 57 + paw[9]; /* ip_dst:16 */ 58 58 /* any options */ 59 59 if (pIpHdr->ip_hl > 20 / 4) 60 60 { 61 /* this is a bit insane... */61 /* this is a bit insane... (identical to the TCP header) */ 62 62 switch (pIpHdr->ip_hl) 63 63 { … … 90 90 * 91 91 * @returns true if valid, false if invalid. 92 * @param pIpHdr Pointer to the IPv4 header to validate. 92 * @param pIpHdr Pointer to the IPv4 header to validate. Network endian (big). 93 93 * @param cbHdrMax The max header size, or the max size of what pIpHdr points 94 94 * to if you like. Note that an IPv4 header can be up to 60 bytes. … … 119 119 120 120 121 /** 122 * Calculates the checksum of a pseudo header given an IPv4 header. 123 * 124 * @returns 32-bit intermediary checksum value. 125 * @param pIpHdr The IP header (network endian (big)). 126 */ 127 RTDECL(uint32_t) RTNetIPv4PseudoChecksum(PCRTNETIPV4 pIpHdr) 128 { 129 uint16_t cbPayload = RT_BE2H_U16(pIpHdr->ip_len) - pIpHdr->ip_hl * 4; 130 uint32_t iSum = pIpHdr->ip_src.au16[0] 131 + pIpHdr->ip_src.au16[1] 132 + pIpHdr->ip_dst.au16[0] 133 + pIpHdr->ip_dst.au16[1] 134 #ifdef RT_BIG_ENDIAN 135 + pIpHdr->ip_p 136 #else 137 + ((uint32_t)pIpHdr->ip_p << 8) 138 #endif 139 + RT_H2BE_U16(cbPayload); 140 return iSum; 141 } 142 143 144 /** 145 * Calculates the checksum of a pseudo header given the individual components. 146 * 147 * @returns 32-bit intermediary checksum value. 148 * @param SrcAddr The source address in host endian. 149 * @param DstAddr The destination address in host endian. 150 * @param bProtocol The protocol number. 151 * @param cbPkt The packet size (host endian of course) (no IPv4 header). 152 */ 153 RTDECL(uint32_t) RTNetIPv4PseudoChecksumBits(RTNETADDRIPV4 SrcAddr, RTNETADDRIPV4 DstAddr, uint8_t bProtocol, uint16_t cbPkt) 154 { 155 uint32_t iSum = RT_H2BE_U16(SrcAddr.au16[0]) 156 + RT_H2BE_U16(SrcAddr.au16[1]) 157 + RT_H2BE_U16(DstAddr.au16[0]) 158 + RT_H2BE_U16(DstAddr.au16[1]) 159 #ifdef RT_BIG_ENDIAN 160 + bProtocol 161 #else 162 + ((uint32_t)bProtocol << 8) 163 #endif 164 + RT_H2BE_U16(cbPkt); 165 return iSum; 166 } 167 168 169 /** 170 * Adds the checksum of the UDP header to the intermediate checksum value. 171 * 172 * @returns 32-bit intermediary checksum value. 173 * @param pUdpHdr Pointer to the UDP header to checksum, network endian (big). 174 * @param iSum The 32-bit intermediate checksum value. 175 */ 176 RTDECL(uint32_t) RTNetIPv4AddUDPChecksum(PCRTNETUDP pUdpHdr, uint32_t iSum) 177 { 178 iSum += pUdpHdr->uh_sport 179 + pUdpHdr->uh_dport 180 /*+ pUdpHdr->uh_sum = 0 */ 181 + pUdpHdr->uh_ulen; 182 return iSum; 183 } 184 185 186 /** 187 * Adds the checksum of the TCP header to the intermediate checksum value. 188 * 189 * @returns 32-bit intermediary checksum value. 190 * @param pUdpHdr Pointer to the TCP header to checksum, network endian (big). 191 * Assums the caller has already validate it and made sure the 192 * entire header is present. 193 * @param iSum The 32-bit intermediate checksum value. 194 */ 195 RTDECL(uint32_t) RTNetIPv4AddTCPChecksum(PCRTNETTCP pTcpHdr, uint32_t iSum) 196 { 197 uint16_t const *paw = (uint16_t const *)pTcpHdr; 198 iSum += paw[0] /* th_sport */ 199 + paw[1] /* th_dport */ 200 + paw[2] /* th_seq */ 201 + paw[3] /* th_seq:16 */ 202 + paw[4] /* th_ack */ 203 + paw[5] /* th_ack:16 */ 204 + paw[6] /* th_off, th_x2, th_flags */ 205 + paw[7] /* th_win */ 206 /*+ paw[8] == 0 */ /* th_sum */ 207 + paw[9]; /* th_urp */ 208 if (pTcpHdr->th_off > RTNETTCP_MIN_LEN / 4) 209 { 210 /* this is a bit insane... (identical to the IPv4 header) */ 211 switch (pTcpHdr->th_off) 212 { 213 case 6: iSum += paw[10] + paw[11]; break; 214 case 7: iSum += paw[10] + paw[11] + paw[12] + paw[13]; break; 215 case 8: iSum += paw[10] + paw[11] + paw[12] + paw[13] + paw[14] + paw[15]; break; 216 case 9: iSum += paw[10] + paw[11] + paw[12] + paw[13] + paw[14] + paw[15] + paw[16] + paw[17]; break; 217 case 10: iSum += paw[10] + paw[11] + paw[12] + paw[13] + paw[14] + paw[15] + paw[16] + paw[17] + paw[18] + paw[19]; break; 218 case 11: iSum += paw[10] + paw[11] + paw[12] + paw[13] + paw[14] + paw[15] + paw[16] + paw[17] + paw[18] + paw[19] + paw[20] + paw[21]; break; 219 case 12: iSum += paw[10] + paw[11] + paw[12] + paw[13] + paw[14] + paw[15] + paw[16] + paw[17] + paw[18] + paw[19] + paw[20] + paw[21] + paw[22] + paw[23]; break; 220 case 13: iSum += paw[10] + paw[11] + paw[12] + paw[13] + paw[14] + paw[15] + paw[16] + paw[17] + paw[18] + paw[19] + paw[20] + paw[21] + paw[22] + paw[23] + paw[24] + paw[25]; break; 221 case 14: iSum += paw[10] + paw[11] + paw[12] + paw[13] + paw[14] + paw[15] + paw[16] + paw[17] + paw[18] + paw[19] + paw[20] + paw[21] + paw[22] + paw[23] + paw[24] + paw[25] + paw[26] + paw[27]; break; 222 case 15: iSum += paw[10] + paw[11] + paw[12] + paw[13] + paw[14] + paw[15] + paw[16] + paw[17] + paw[18] + paw[19] + paw[20] + paw[21] + paw[22] + paw[23] + paw[24] + paw[25] + paw[26] + paw[27] + paw[28] + paw[29]; break; 223 default: 224 AssertFailed(); 225 } 226 } 227 228 return iSum; 229 } 230 231 232 /** 233 * Adds the checksum of the specified data segment to the intermediate checksum value. 234 * 235 * @returns 32-bit intermediary checksum value. 236 * @param pUdpHdr Pointer to the UDP header to checksum, network endian (big). 237 * @param iSum The 32-bit intermediate checksum value. 238 * @param pfOdd This is used to keep track of odd bits, initialize to false 239 * when starting to checksum the data (aka text) after a TCP 240 * or UDP header (data never start at an odd offset). 241 */ 242 RTDECL(uint32_t) RTNetIPv4AddDataChecksum(void const *pvData, size_t cbData, uint32_t iSum, bool *pfOdd) 243 { 244 if (*pfOdd) 245 { 246 #ifdef RT_BIG_ENDIAN 247 /* there was an odd byte in the previous chunk, add the lower byte. */ 248 iSum += *(uint8_t *)pvData; 249 #else 250 /* there was an odd byte in the previous chunk, add the upper byte. */ 251 iSum += (uint32_t)*(uint8_t *)pvData << 8; 252 #endif 253 /* skip the byte. */ 254 cbData--; 255 if (!cbData) 256 return iSum; 257 pvData = (uint8_t const *)pvData + 1; 258 } 259 260 /* iterate the data. */ 261 uint16_t const *pw = (uint16_t const *)pvData; 262 while (cbData > 1) 263 { 264 iSum += *pw; 265 pw += 2; 266 cbData -= 2; 267 } 268 269 /* handle odd byte. */ 270 if (cbData) 271 { 272 #ifdef RT_BIG_ENDIAN 273 iSum += (uint32_t)*(uint8_t *)pw << 8; 274 #else 275 iSum += *(uint8_t *)pw; 276 #endif 277 *pfOdd = true; 278 } 279 else 280 *pfOdd = false; 281 return iSum; 282 } 283 284 285 /** 286 * Finalizes a IPv4 checksum. 287 * 288 * @returns The checksum. 289 * @param iSum The 32-bit intermediate checksum value. 290 */ 291 RTDECL(uint16_t) RTNetIPv4FinalizeChecksum(uint32_t iSum) 292 { 293 /* 16-bit one complement fun */ 294 iSum = (iSum >> 16) + (iSum & 0xffff); /* hi + low words */ 295 iSum += iSum >> 16; /* carry */ 296 return (uint16_t)~iSum; 297 } 298 299 300
Note:
See TracChangeset
for help on using the changeset viewer.