checkSum的计算
Posted 我要出家当道士
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了checkSum的计算相关的知识,希望对你有一定的参考价值。
目录
1、Introduction
下面主要介绍IP协议与UDP协议中校验和的计算(TCP与UDP类似),主要是自己记录一下,以后可以快速使用。传输层的以 UDP 为例。
IP与UDP的校验和算法是一样的,都遵循 RFC1071。唯一的不同在于 IP 校验和的范围只包含 IP 头部,而 UDP 则包含 伪头部,UDP 头部 和 数据部分。UDP及其伪头部如下图所示。
2、CheckSum Function(GO)
func checksum(data []byte) uint16 {
csum := uint32(0)
length := len(data) - 1
for i := 0; i < length; i += 2 {
csum += uint32(data[i]) << 8
csum += uint32(data[i+1])
}
if len(data)%2 == 1 {
csum += uint32(data[length]) << 8
}
for csum > 0xffff {
csum = (csum >> 16) + (csum & 0xffff)
}
return ^uint16(csum)
}
3、demo(GO)
package main
import (
"golang.org/x/sys/unix"
"log"
"net"
)
func checksum(data []byte) uint16 {
csum := uint32(0)
length := len(data) - 1
for i := 0; i < length; i += 2 {
// For our test packet, doing this manually is about 25% faster
// (740 ns vs. 1000ns) than doing it by calling binary.BigEndian.Uint16.
csum += uint32(data[i]) << 8
csum += uint32(data[i+1])
}
if len(data)%2 == 1 {
csum += uint32(data[length]) << 8
}
for csum > 0xffff {
csum = (csum >> 16) + (csum & 0xffff)
}
return ^uint16(csum)
}
func rawSocket(ifaceName string) (fd int, err error) {
protol := (unix.ETH_P_ALL<<8)&0xff00 | unix.ETH_P_ALL>>8
fd, err = unix.Socket(unix.AF_PACKET, unix.SOCK_RAW, int(protol))
if err != nil {
return -1, err
}
ifIndex := 0
if ifaceName != "" {
iface, err := net.InterfaceByName(ifaceName)
if err != nil {
return -1, err
}
ifIndex = iface.Index
}
s := &unix.SockaddrLinklayer{
Protocol: uint16(protol),
Ifindex: ifIndex,
}
err = unix.Bind(fd, s)
return fd, err
}
var buff = []byte{0,12,41,222,152,91,0,12,41,222,152,91,8,0,69,0,0,38,159,34,64,0,64,17,0,0,192,168,2,201,192,168,2,201,
29,50,29,49,0,18,0,0,1,1,1,1,1,1,1,1,1,1}
func main(){
fd, _ := rawSocket("ens33")
// ip
cs := checksum(buff[14:34])
buff[24] = byte(cs >> 8)
buff[25] = byte(cs & 0xff)
// udp
ud := make([]byte, 12 + 8 + 10)
copy(ud[:4], buff[26:30])
copy(ud[4:8], buff[30:34])
ud[8] = 0
ud[9] = 17
ud[10] = 0
ud[11] = 18
copy(ud[12:], buff[34:])
ucs := checksum(ud)
buff[40] = byte(ucs >> 8)
buff[41] = byte(ucs & 0xff)
log.Print(buff)
unix.Write(fd, buff)
}
以上是关于checkSum的计算的主要内容,如果未能解决你的问题,请参考以下文章