a go dns packet parser
1package magna 2 3import ( 4 "encoding/binary" 5 "fmt" 6 "net" 7 "strings" 8) 9 10func (a *A) Decode(buf []byte, offset int, rdlength int) (int, error) { 11 bytes, offset, err := getSlice(buf, offset, rdlength) 12 if err != nil { 13 return offset, err 14 } 15 16 a.Address = net.IP(bytes) 17 return offset, err 18} 19 20func (a *A) Encode(bytes []byte, offsets *map[string]uint16) []byte { 21 return append(bytes, a.Address.To4()...) 22} 23 24func (a A) String() string { 25 return a.Address.String() 26} 27 28func (ns *NS) Decode(buf []byte, offset int, rdlength int) (int, error) { 29 var err error 30 ns.NSDName, offset, err = decode_domain(buf, offset) 31 if err != nil { 32 return offset, err 33 } 34 35 return offset, err 36} 37 38func (ns *NS) Encode(bytes []byte, offsets *map[string]uint16) []byte { 39 return encode_domain(bytes, ns.NSDName, offsets) 40} 41 42func (ns NS) String() string { 43 return ns.NSDName 44} 45 46func (md *MD) Decode(buf []byte, offset int, rdlength int) (int, error) { 47 var err error 48 md.MADName, offset, err = decode_domain(buf, offset) 49 if err != nil { 50 return offset, err 51 } 52 53 return offset, err 54} 55 56func (md *MD) Encode(bytes []byte, offsets *map[string]uint16) []byte { 57 return encode_domain(bytes, md.MADName, offsets) 58} 59 60func (md MD) String() string { 61 return md.MADName 62} 63 64func (mf *MF) Decode(buf []byte, offset int, rdlength int) (int, error) { 65 var err error 66 mf.MADName, offset, err = decode_domain(buf, offset) 67 if err != nil { 68 return offset, err 69 } 70 71 return offset, err 72} 73 74func (mf *MF) Encode(bytes []byte, offsets *map[string]uint16) []byte { 75 return encode_domain(bytes, mf.MADName, offsets) 76} 77 78func (mf MF) String() string { 79 return mf.MADName 80} 81 82func (c *CNAME) Decode(buf []byte, offset int, rdlength int) (int, error) { 83 var err error 84 c.CName, offset, err = decode_domain(buf, offset) 85 if err != nil { 86 return offset, err 87 } 88 89 return offset, err 90} 91 92func (c *CNAME) Encode(bytes []byte, offsets *map[string]uint16) []byte { 93 return encode_domain(bytes, c.CName, offsets) 94} 95 96func (c CNAME) String() string { 97 return c.CName 98} 99 100func (soa *SOA) Decode(buf []byte, offset int, rdlength int) (int, error) { 101 var err error 102 soa.MName, offset, err = decode_domain(buf, offset) 103 if err != nil { 104 return offset, err 105 } 106 107 soa.RName, offset, err = decode_domain(buf, offset) 108 if err != nil { 109 return offset, err 110 } 111 112 soa.Serial, offset, err = getU32(buf, offset) 113 if err != nil { 114 return offset, err 115 } 116 117 soa.Refresh, offset, err = getU32(buf, offset) 118 if err != nil { 119 return offset, err 120 } 121 122 soa.Retry, offset, err = getU32(buf, offset) 123 if err != nil { 124 return offset, err 125 } 126 127 soa.Expire, offset, err = getU32(buf, offset) 128 if err != nil { 129 return offset, err 130 } 131 132 soa.Minimum, offset, err = getU32(buf, offset) 133 if err != nil { 134 return offset, err 135 } 136 137 return offset, err 138} 139 140func (soa *SOA) Encode(bytes []byte, offsets *map[string]uint16) []byte { 141 bytes = encode_domain(bytes, soa.MName, offsets) 142 bytes = encode_domain(bytes, soa.RName, offsets) 143 bytes = binary.BigEndian.AppendUint32(bytes, soa.Serial) 144 bytes = binary.BigEndian.AppendUint32(bytes, soa.Refresh) 145 bytes = binary.BigEndian.AppendUint32(bytes, soa.Retry) 146 bytes = binary.BigEndian.AppendUint32(bytes, soa.Expire) 147 bytes = binary.BigEndian.AppendUint32(bytes, soa.Minimum) 148 149 return bytes 150} 151 152func (soa SOA) String() string { 153 return fmt.Sprintf("%s %s %d %d %d %d %d", soa.MName, soa.RName, soa.Serial, soa.Refresh, soa.Retry, soa.Expire, soa.Minimum) 154} 155 156func (mb *MB) Decode(buf []byte, offset int, rdlength int) (int, error) { 157 madname, offset, err := decode_domain(buf, offset) 158 if err != nil { 159 return offset, err 160 } 161 162 mb.MADName = string(madname) 163 return offset, err 164} 165 166func (mb *MB) Encode(bytes []byte, offsets *map[string]uint16) []byte { 167 return encode_domain(bytes, mb.MADName, offsets) 168} 169 170func (mb MB) String() string { 171 return mb.MADName 172} 173 174func (mg *MG) Decode(buf []byte, offset int, rdlength int) (int, error) { 175 var err error 176 mg.MGMName, offset, err = decode_domain(buf, offset) 177 if err != nil { 178 return offset, err 179 } 180 181 return offset, err 182} 183 184func (mg *MG) Encode(bytes []byte, offsets *map[string]uint16) []byte { 185 return encode_domain(bytes, mg.MGMName, offsets) 186} 187 188func (mg MG) String() string { 189 return mg.MGMName 190} 191 192func (mr *MR) Decode(buf []byte, offset int, rdlength int) (int, error) { 193 var err error 194 mr.NEWName, offset, err = decode_domain(buf, offset) 195 if err != nil { 196 return offset, err 197 } 198 199 return offset, err 200} 201 202func (mr *MR) Encode(bytes []byte, offsets *map[string]uint16) []byte { 203 return encode_domain(bytes, mr.NEWName, offsets) 204} 205 206func (mr MR) String() string { 207 return mr.NEWName 208} 209 210func (null *NULL) Decode(buf []byte, offset int, rdlength int) (int, error) { 211 var err error 212 null.Anything, offset, err = getSlice(buf, offset, int(rdlength)) 213 if err != nil { 214 return offset, err 215 } 216 217 return offset, err 218} 219 220func (null *NULL) Encode(bytes []byte, offsets *map[string]uint16) []byte { 221 return append(bytes, null.Anything...) 222} 223 224func (null NULL) String() string { 225 return string(null.Anything) 226} 227 228func (wks *WKS) Decode(buf []byte, offset int, rdlength int) (int, error) { 229 address, offset, err := getSlice(buf, offset, 4) 230 if err != nil { 231 return offset, err 232 } 233 234 protocol, offset, err := getU8(buf, offset) 235 if err != nil { 236 return offset, err 237 } 238 239 wks.Address = net.IP(address) 240 wks.Protocol = protocol 241 wks.BitMap, offset, err = getSlice(buf, offset, offset+int(rdlength)-5) 242 if err != nil { 243 return offset, err 244 } 245 246 return offset, err 247} 248 249func (wks *WKS) Encode(bytes []byte, offsets *map[string]uint16) []byte { 250 bytes = append(bytes, wks.Address.To4()...) 251 bytes = append(bytes, wks.Protocol) 252 bytes = append(bytes, wks.BitMap...) 253 254 return bytes 255} 256 257func (wks WKS) String() string { 258 return fmt.Sprintf("%s %d %s", wks.Address.String(), wks.Protocol, wks.BitMap) 259} 260 261func (ptr *PTR) Decode(buf []byte, offset int, rdlength int) (int, error) { 262 var err error 263 ptr.PTRDName, offset, err = decode_domain(buf, offset) 264 if err != nil { 265 return offset, err 266 } 267 268 return offset, err 269} 270 271func (ptr *PTR) Encode(bytes []byte, offsets *map[string]uint16) []byte { 272 return encode_domain(bytes, ptr.PTRDName, offsets) 273} 274 275func (ptr PTR) String() string { 276 return ptr.PTRDName 277} 278 279func (hinfo *HINFO) Decode(buf []byte, offset int, rdlength int) (int, error) { 280 input, offset, err := getSlice(buf, offset, int(rdlength)) 281 if err != nil { 282 return offset, err 283 } 284 285 parts := strings.SplitN(string(input), " ", 2) 286 if len(parts) != 2 { 287 return offset, &MagnaError{Message: "HINFO expected 2 values separated by a space"} 288 } 289 290 hinfo.CPU = parts[0] 291 hinfo.OS = parts[1] 292 return offset, err 293} 294 295func (hinfo *HINFO) Encode(bytes []byte, offsets *map[string]uint16) []byte { 296 bytes = append(bytes, []byte(hinfo.CPU)...) 297 bytes = append(bytes, ' ') 298 bytes = append(bytes, []byte(hinfo.OS)...) 299 return bytes 300} 301 302func (hinfo HINFO) String() string { 303 return hinfo.OS + " " + hinfo.CPU 304} 305 306func (minfo *MINFO) Decode(buf []byte, offset int, rdlength int) (int, error) { 307 var err error 308 309 minfo.RMailBx, offset, err = decode_domain(buf, offset) 310 if err != nil { 311 return offset, err 312 } 313 314 minfo.EMailBx, offset, err = decode_domain(buf, offset) 315 if err != nil { 316 return offset, err 317 } 318 319 return offset, err 320} 321 322func (minfo *MINFO) Encode(bytes []byte, offsets *map[string]uint16) []byte { 323 bytes = encode_domain(bytes, minfo.RMailBx, offsets) 324 bytes = encode_domain(bytes, minfo.EMailBx, offsets) 325 326 return bytes 327} 328 329func (minfo MINFO) String() string { 330 return minfo.RMailBx + " " + minfo.EMailBx 331} 332 333func (mx *MX) Decode(buf []byte, offset int, rdlength int) (int, error) { 334 var err error 335 mx.Preference, offset, err = getU16(buf, offset) 336 if err != nil { 337 return offset, err 338 } 339 340 mx.Exchange, offset, err = decode_domain(buf, offset) 341 if err != nil { 342 return offset, err 343 } 344 345 return offset, err 346} 347 348func (mx *MX) Encode(bytes []byte, offsets *map[string]uint16) []byte { 349 bytes = binary.BigEndian.AppendUint16(bytes, mx.Preference) 350 bytes = encode_domain(bytes, mx.Exchange, offsets) 351 352 return bytes 353} 354 355func (mx MX) String() string { 356 return fmt.Sprintf("%d %s", mx.Preference, mx.Exchange) 357} 358 359func (txt *TXT) Decode(buf []byte, offset int, rdlength int) (int, error) { 360 bytes, offset, err := getSlice(buf, offset, rdlength) 361 if err != nil { 362 return offset, err 363 } 364 365 txt.TxtData = string(bytes) 366 return offset, err 367} 368 369func (txt *TXT) Encode(bytes []byte, offsets *map[string]uint16) []byte { 370 return append(bytes, []byte(txt.TxtData)...) 371} 372 373func (txt TXT) String() string { 374 return txt.TxtData 375} 376 377func (r *Reserved) Decode(buf []byte, offset int, rdlength int) (int, error) { 378 var err error 379 r.Bytes, offset, err = getSlice(buf, offset, int(rdlength)) 380 if err != nil { 381 return offset, err 382 } 383 384 return offset, err 385} 386 387func (r *Reserved) Encode(bytes []byte, offsets *map[string]uint16) []byte { 388 return append(bytes, r.Bytes...) 389} 390 391func (r Reserved) String() string { 392 return string(r.Bytes) 393} 394 395// Decode decodes a resource record from buf at the offset. 396func (r *ResourceRecord) Decode(buf []byte, offset int) (int, error) { 397 name, offset, err := decode_domain(buf, offset) 398 if err != nil { 399 return offset, err 400 } 401 r.Name = name 402 403 rtype, offset, err := getU16(buf, offset) 404 if err != nil { 405 return offset, err 406 } 407 r.RType = DNSType(rtype) 408 409 rclass, offset, err := getU16(buf, offset) 410 if err != nil { 411 return offset, err 412 } 413 r.RClass = DNSClass(rclass) 414 415 r.TTL, offset, err = getU32(buf, offset) 416 if err != nil { 417 return offset, err 418 } 419 420 r.RDLength, offset, err = getU16(buf, offset) 421 if err != nil { 422 return offset, err 423 } 424 425 switch r.RType { 426 case 1: 427 r.RData = &A{} 428 case 2: 429 r.RData = &NS{} 430 case 3: 431 r.RData = &MD{} 432 case 4: 433 r.RData = &MF{} 434 case 5: 435 r.RData = &CNAME{} 436 case 6: 437 r.RData = &SOA{} 438 case 7: 439 r.RData = &MB{} 440 case 8: 441 r.RData = &MG{} 442 case 9: 443 r.RData = &MR{} 444 case 10: 445 r.RData = &NULL{} 446 case 11: 447 r.RData = &WKS{} 448 case 12: 449 r.RData = &PTR{} 450 case 13: 451 r.RData = &HINFO{} 452 case 14: 453 r.RData = &MINFO{} 454 case 15: 455 r.RData = &MX{} 456 case 16: 457 r.RData = &TXT{} 458 default: 459 r.RData = &Reserved{} 460 } 461 462 if r.RData != nil { 463 offset, err = r.RData.Decode(buf, offset, int(r.RDLength)) 464 if err != nil { 465 return offset, err 466 } 467 } 468 469 return offset, nil 470} 471 472// Encode encdoes a resource record and returns the input bytes appened. 473func (r *ResourceRecord) Encode(bytes []byte, offsets *map[string]uint16) []byte { 474 bytes = encode_domain(bytes, r.Name, offsets) 475 bytes = binary.BigEndian.AppendUint16(bytes, uint16(r.RType)) 476 bytes = binary.BigEndian.AppendUint16(bytes, uint16(r.RClass)) 477 bytes = binary.BigEndian.AppendUint32(bytes, r.TTL) 478 479 rdata_start := len(bytes) 480 bytes = binary.BigEndian.AppendUint16(bytes, 0) 481 bytes = r.RData.Encode(bytes, offsets) 482 rdata_length := uint16(len(bytes) - rdata_start - 2) 483 binary.BigEndian.PutUint16(bytes[rdata_start:rdata_start+2], rdata_length) 484 485 return bytes 486}