-- (c) William Welch 2004 -- -- This software is provided 'as-is', without any express or implied -- warranty. In no event will the authors be held liable for any damages -- arising from the use of this software. -- -- Permission is granted to anyone to use this software for any purpose, -- including commercial applications, and to alter it and redistribute it -- freely, subject to the following restrictions: -- -- 1. The origin of this software must not be misrepresented; -- you must not claim that you wrote the original software. -- If you use this software in a product, an acknowledgment in -- the product documentation would be appreciated but is not required. -- -- 2. Altered source versions must be plainly marked as such, and must -- not be misrepresented as being the original software. -- -- 3. This notice may not be removed or altered from any source distribution. -- -- This license is commonly known as the zlib/libpng License. -- -- chksum.jal bvwelch 20 may 2004 -- revised 18 march 2005 -- Internet Checksum in JAL, see RFC 1071. -- prepare for checksum calculations procedure chksum_start is I32_CLR ( SUM32 ) end procedure -- compare to "C" example, RFC 1071, section 4.1, page 7. procedure chksum_calc (byte in ptr, byte in offset, byte in cnt_hi, byte in cnt_lo) is var byte hi, lo LoadPointer_2 ( ptr , offset ) while cnt_hi > 0 loop for 128 loop hi = MemNext2 lo = MemNext2 I32_LDL ( CHKTMP , 0 , 0 , hi , lo ) I32_ADD ( SUM32 , CHKTMP ) end loop cnt_hi = cnt_hi - 1 end loop while cnt_lo > 1 loop hi = MemNext2 lo = MemNext2 I32_LDL ( CHKTMP , 0 , 0 , hi , lo ) I32_ADD ( SUM32 , CHKTMP ) cnt_lo = cnt_lo - 2 end loop if cnt_lo > 0 then hi = MemNext2 I32_LDL ( CHKTMP , 0 , 0 , hi , 0 ) I32_ADD ( SUM32 , CHKTMP ) end if end procedure procedure chksum_finish (byte out sum_hi, byte out sum_lo) is var byte b3 , b2 , b1 , b0 I32_SVL ( SUM32 , b3 , b2 , b1 , b0 ) while ( b3 != 0 ) | ( b2 != 0 ) loop I32_LDL ( CHKTMP , 0 , 0 , b3 , b2 ) I32_LDL ( SUM32 , 0 , 0 , b1 , b0 ) I32_ADD ( SUM32 , CHKTMP ) I32_SVL ( SUM32 , b3 , b2 , b1 , b0 ) end loop sum_hi = b1 sum_lo = b0 end procedure -- regression test from RFC 1071 -- answer should be 0xDDF2 procedure chksum_test is var byte sum_hi, sum_lo LoadPointer_0 ( PKT ) MemNext = 0x00 MemNext = 0x01 MemNext = 0xf2 MemNext = 0x03 MemNext = 0xf4 MemNext = 0xf5 MemNext = 0xf6 MemNext = 0xf7 chksum_start chksum_calc(PKT, 0, 0, 8) chksum_finish(sum_hi, sum_lo) putc = "C" putc = "H" putc = "K" putc = "S" putc = "U" putc = "M" putc = " " if (sum_hi == 0xDD) & (sum_lo == 0xF2) then putc = "O" putc = "K" else putc = "B" putc = "A" putc = "D" end if putc = 13 putc = 10 end procedure -- compute and store the checksum procedure chksum_write(byte in ptr , byte in start_offset, byte in write_offset, byte in cnt_hi , byte in cnt_lo) is var byte sum_hi, sum_lo -- first, zero out where the checksum goes. MemSetEx ( ptr , write_offset , 0 , 2 ) chksum_start chksum_calc(ptr, start_offset, cnt_hi , cnt_lo) chksum_finish(sum_hi, sum_lo) -- store the ones-complement of the checksum. MemWrEx (ptr , write_offset, (sum_hi ^ 0xff) ) MemWrEx( ptr , (write_offset + 1), (sum_lo ^ 0xff) ) end procedure procedure chksum_udp is var byte cnt_hi, cnt_lo, sum_hi, sum_lo -- build pseudo header MemCpyEx ( UDP_PSEUDO , 0 , ip_off , 12 , 8 ) MemWrEx( UDP_PSEUDO , 8 , 0) MemCpyEx( UDP_PSEUDO , 9 , ip_off , 9 , 1 ) MemCpyEx( UDP_PSEUDO , 10, udp_off , 4 , 2 ) -- now calculate the checksum of the pseudo header. chksum_start chksum_calc(UDP_PSEUDO, 0, 0 , 12) -- now calculate the checksum of the udp packet itself MemSetEx( udp_off , 6, 0 , 2 ) -- note byte swap I16_SVL ( UDP_LEN , cnt_lo , cnt_hi) chksum_calc( udp_off, 0 , cnt_hi , cnt_lo) chksum_finish(sum_hi, sum_lo) -- store the ones-complement of the checksum. MemWrEx ( udp_off , 6, (sum_hi ^ 0xff) ) MemWrEx ( udp_off , 7, (sum_lo ^ 0xff) ) end procedure procedure chksum_tcp(byte in tcplen_hi , byte in tcplen_lo) is var byte sum_hi, sum_lo -- build pseudo header MemCpyEx ( TCP_PSEUDO , 0 , IP_OFF , 12 , 8 ) MemWrEx ( tcp_pseudo , 8, 0) MemCpyEx( tcp_pseudo , 9, ip_off , 9 , 1 ) MemWrEx ( tcp_pseudo , 10, tcplen_hi) MemWrEx ( tcp_pseudo , 11, tcplen_lo) -- now calculate the checksum of the pseudo header. chksum_start chksum_calc(tcp_pseudo, 0, 0 , 12) -- now calculate the checksum of the tcp packet itself MemSetEx ( tcp_off , 16, 0, 2) chksum_calc(tcp_off, 0, tcplen_hi , tcplen_lo) chksum_finish(sum_hi, sum_lo) -- store the ones-complement of the checksum. MemWrEx( tcp_off , 16, (sum_hi ^ 0xff) ) MemWrEx( tcp_off , 17, (sum_lo ^ 0xff) ) end procedure