Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ examples/reassemblydump/reassemblydump
layers/gen
macs/gen
pcap/pcap_tester
.idea/
60 changes: 33 additions & 27 deletions layers/ip4.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,24 +190,9 @@ func (ip *IPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
df.SetTruncated()
return fmt.Errorf("Invalid ip4 header. Length %d less than 20", len(data))
}
flagsfrags := binary.BigEndian.Uint16(data[6:8])

ip.Version = uint8(data[0]) >> 4
ip.IHL = uint8(data[0]) & 0x0F
ip.TOS = data[1]
ip.Length = binary.BigEndian.Uint16(data[2:4])
ip.Id = binary.BigEndian.Uint16(data[4:6])
ip.Flags = IPv4Flag(flagsfrags >> 13)
ip.FragOffset = flagsfrags & 0x1FFF
ip.TTL = data[8]
ip.Protocol = IPProtocol(data[9])
ip.Checksum = binary.BigEndian.Uint16(data[10:12])
ip.SrcIP = data[12:16]
ip.DstIP = data[16:20]
ip.Options = ip.Options[:0]
ip.Padding = nil
// Set up an initial guess for contents/payload... we'll reset these soon.
ip.BaseLayer = BaseLayer{Contents: data}
ip.IHL = uint8(data[0]) & 0x0F

// This code is added for the following enviroment:
// * Windows 10 with TSO option activated. ( tested on Hyper-V, RealTek ethernet driver )
Expand All @@ -224,6 +209,7 @@ func (ip *IPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
} else if int(ip.IHL*4) > int(ip.Length) {
return fmt.Errorf("Invalid IP header length > IP length (%d > %d)", ip.IHL, ip.Length)
}

if cmp := len(data) - int(ip.Length); cmp > 0 {
data = data[:ip.Length]
} else if cmp < 0 {
Expand All @@ -232,45 +218,65 @@ func (ip *IPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
return errors.New("Not all IP header bytes available")
}
}

ip.Options = ip.Options[:0]
ip.Contents = data[:ip.IHL*4]
ip.Payload = data[ip.IHL*4:]

// From here on, data contains the header options.
data = data[20 : ip.IHL*4]
headerOptionsData := data[20 : ip.IHL*4]
// Pull out IP options
for len(data) > 0 {
for len(headerOptionsData) > 0 {
if ip.Options == nil {
// Pre-allocate to avoid growing the slice too much.
ip.Options = make([]IPv4Option, 0, 4)
}
opt := IPv4Option{OptionType: data[0]}

opt := IPv4Option{OptionType: headerOptionsData[0]}
switch opt.OptionType {
case 0: // End of options
opt.OptionLength = 1
ip.Options = append(ip.Options, opt)
ip.Padding = data[1:]
ip.Padding = headerOptionsData[1:]

return nil
case 1: // 1 byte padding
opt.OptionLength = 1
data = data[1:]
headerOptionsData = headerOptionsData[1:]
ip.Options = append(ip.Options, opt)
default:
if len(data) < 2 {
if len(headerOptionsData) < 2 {
df.SetTruncated()
return fmt.Errorf("Invalid ip4 option length. Length %d less than 2", len(data))
return fmt.Errorf("Invalid ip4 option length. Length %d less than 2", len(headerOptionsData))
}
opt.OptionLength = data[1]
if len(data) < int(opt.OptionLength) {

opt.OptionLength = headerOptionsData[1]
if len(headerOptionsData) < int(opt.OptionLength) {
df.SetTruncated()
return fmt.Errorf("IP option length exceeds remaining IP header size, option type %v length %v", opt.OptionType, opt.OptionLength)
}
if opt.OptionLength <= 2 {
return fmt.Errorf("Invalid IP option type %v length %d. Must be greater than 2", opt.OptionType, opt.OptionLength)
}
opt.OptionData = data[2:opt.OptionLength]
data = data[opt.OptionLength:]
opt.OptionData = headerOptionsData[2:opt.OptionLength]
headerOptionsData = headerOptionsData[opt.OptionLength:]
ip.Options = append(ip.Options, opt)
}
}

flagsfrags := binary.BigEndian.Uint16(data[6:8])
ip.Version = data[0] >> 4
ip.TOS = data[1]
ip.Id = binary.BigEndian.Uint16(data[4:6])
ip.Flags = IPv4Flag(flagsfrags >> 13)
ip.FragOffset = flagsfrags & 0x1FFF
ip.TTL = data[8]
ip.Protocol = IPProtocol(data[9])
ip.Checksum = binary.BigEndian.Uint16(data[10:12])
ip.SrcIP = data[12:16]
ip.DstIP = data[16:20]
ip.Padding = nil

return nil
}

Expand Down
Loading