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