DecodeFromBytes decodes the slice into the DNS struct.
(data []byte, df gopacket.DecodeFeedback)
| 302 | |
| 303 | // DecodeFromBytes decodes the slice into the DNS struct. |
| 304 | func (d *DNS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { |
| 305 | d.buffer = d.buffer[:0] |
| 306 | |
| 307 | if len(data) < 12 { |
| 308 | df.SetTruncated() |
| 309 | return errDNSPacketTooShort |
| 310 | } |
| 311 | |
| 312 | // since there are no further layers, the baselayer's content is |
| 313 | // pointing to this layer |
| 314 | d.BaseLayer = BaseLayer{Contents: data[:len(data)]} |
| 315 | d.ID = binary.BigEndian.Uint16(data[:2]) |
| 316 | d.QR = data[2]&0x80 != 0 |
| 317 | d.OpCode = DNSOpCode(data[2]>>3) & 0x0F |
| 318 | d.AA = data[2]&0x04 != 0 |
| 319 | d.TC = data[2]&0x02 != 0 |
| 320 | d.RD = data[2]&0x01 != 0 |
| 321 | d.RA = data[3]&0x80 != 0 |
| 322 | d.Z = uint8(data[3]>>4) & 0x7 |
| 323 | d.ResponseCode = DNSResponseCode(data[3] & 0xF) |
| 324 | d.QDCount = binary.BigEndian.Uint16(data[4:6]) |
| 325 | d.ANCount = binary.BigEndian.Uint16(data[6:8]) |
| 326 | d.NSCount = binary.BigEndian.Uint16(data[8:10]) |
| 327 | d.ARCount = binary.BigEndian.Uint16(data[10:12]) |
| 328 | |
| 329 | d.Questions = d.Questions[:0] |
| 330 | d.Answers = d.Answers[:0] |
| 331 | d.Authorities = d.Authorities[:0] |
| 332 | d.Additionals = d.Additionals[:0] |
| 333 | |
| 334 | offset := 12 |
| 335 | var err error |
| 336 | for i := 0; i < int(d.QDCount); i++ { |
| 337 | var q DNSQuestion |
| 338 | if offset, err = q.decode(data, offset, df, &d.buffer); err != nil { |
| 339 | return err |
| 340 | } |
| 341 | d.Questions = append(d.Questions, q) |
| 342 | } |
| 343 | |
| 344 | // For some horrible reason, if we do the obvious thing in this loop: |
| 345 | // var r DNSResourceRecord |
| 346 | // if blah := r.decode(blah); err != nil { |
| 347 | // return err |
| 348 | // } |
| 349 | // d.Foo = append(d.Foo, r) |
| 350 | // the Go compiler thinks that 'r' escapes to the heap, causing a malloc for |
| 351 | // every Answer, Authority, and Additional. To get around this, we do |
| 352 | // something really silly: we append an empty resource record to our slice, |
| 353 | // then use the last value in the slice to call decode. Since the value is |
| 354 | // already in the slice, there's no WAY it can escape... on the other hand our |
| 355 | // code is MUCH uglier :( |
| 356 | for i := 0; i < int(d.ANCount); i++ { |
| 357 | d.Answers = append(d.Answers, DNSResourceRecord{}) |
| 358 | if offset, err = d.Answers[i].decode(data, offset, df, &d.buffer); err != nil { |
| 359 | d.Answers = d.Answers[:i] // strip off erroneous value |
| 360 | return err |
| 361 | } |