既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
概览
NewPacketSource
NewPacketSource 其参数需要两个接口 PacketDataSource 和 Decoder,PacketDataSource 为数据包,一般我们使用 handle,Decoder 为解码器,一般我们都使用 hanler.LinkType 来传递
func NewPacketSource(source PacketDataSource, decoder Decoder) \*PacketSource {
return &PacketSource{
source: source,
decoder: decoder,
}
}
handle.LinkType
handle.LinkType()是源的链路层类型,一般是 LinkType 对应枚举 LinkTypeEthernet
func (p \*Handle) LinkType() layers.LinkType {
return p.pcapDatalink()
}
func (p \*Handle) pcapDatalink() layers.LinkType {
ret, \_, \_ := syscall.Syscall(pcapDatalinkPtr, 1, uintptr(p.cptr), 0, 0)
return layers.LinkType(ret)
}
LinkType
type LinkType uint8
func (a LinkType) Decode(data []byte, p gopacket.PacketBuilder) error {
return LinkTypeMetadata[a].DecodeWith.Decode(data, p)
}
那么 LinkTypeMetadata 数据是从那里呢?我们可以借助 IDE 的全局查找功能进行查找
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WESNx1yE-1659280486701)(assets/image-20220729111733-0mflbru.png)]
查找后我们可以在 layers.enums.go 大约 368 行看到 LinkTypeEthernet 的注册信息
LinkTypeMetadata[LinkTypeEthernet] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeEthernet), Name: "Ethernet"}
然后反推其调用链为 init->initActualTypeData
func init() {
initUnknownTypesForLinkType()
initUnknownTypesForEthernetType()
initUnknownTypesForPPPType()
initUnknownTypesForIPProtocol()
initUnknownTypesForSCTPChunkType()
initUnknownTypesForPPPoECode()
initUnknownTypesForFDDIFrameControl()
initUnknownTypesForEAPOLType()
initUnknownTypesForProtocolFamily()
initUnknownTypesForDot11Type()
initUnknownTypesForUSBTransportType()
initActualTypeData()
}
func initActualTypeData() {
...
LinkTypeMetadata[LinkTypeEthernet] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeEthernet), Name: "Ethernet"}
...
}
decodeEthernet
func decodeEthernet(data []byte, p gopacket.PacketBuilder) error {
eth := &Ethernet{}
err := eth.DecodeFromBytes(data, p)
if err != nil {
return err
}
p.AddLayer(eth)
p.SetLinkLayer(eth)
return p.NextDecoder(eth.EthernetType)
}
然后我们可以看到 ether 的解析过程
func (eth \*Ethernet) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
if len(data) < 14 {
return errors.New("Ethernet packet too small")
}
eth.DstMAC = net.HardwareAddr(data[0:6])
eth.SrcMAC = net.HardwareAddr(data[6:12])
eth.EthernetType = EthernetType(binary.BigEndian.Uint16(data[12:14]))
eth.BaseLayer = BaseLayer{data[:14], data[14:]}
eth.Length = 0
if eth.EthernetType < 0x0600 {
eth.Length = uint16(eth.EthernetType)
eth.EthernetType = EthernetTypeLLC
if cmp := len(eth.Payload) - int(eth.Length); cmp < 0 {
df.SetTruncated()
} else if cmp > 0 {
// Strip off bytes at the end, since we have too many bytes
eth.Payload = eth.Payload[:len(eth.Payload)-cmp]
}
// fmt.Println(eth)
}
return nil
}
NextPacket
func (p \*PacketSource) NextPacket() (Packet, error) {
data, ci, err := p.source.ReadPacketData()
if err != nil {
return nil, err
}
packet := NewPacket(data, p.decoder, p.DecodeOptions)
m := packet.Metadata()
m.CaptureInfo = ci
m.Truncated = m.Truncated || ci.CaptureLength < ci.Length
return packet, nil
}
NewPacket
func NewPacket(data []byte, firstLayerDecoder Decoder, options DecodeOptions) Packet {
if !options.NoCopy {
dataCopy := make([]byte, len(data))
copy(dataCopy, data)
data = dataCopy
}
if options.Lazy {
p := &lazyPacket{
packet: packet{data: data, decodeOptions: options},
next: firstLayerDecoder,
![img](https://img-blog.csdnimg.cn/img_convert/9f0acc27666f22606f91e0c4d7259651.png)
![img](https://img-blog.csdnimg.cn/img_convert/f575c04207fe589dea09235add561046.png)
![img](https://img-blog.csdnimg.cn/img_convert/130a09bdee72105ef194f2ad280d9e68.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**
习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**