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]uint8) []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]uint8) []byte {
39 return append(bytes, 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]uint8) []byte {
57 return append(bytes, 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]uint8) []byte {
75 return append(bytes, 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]uint8) []byte {
93 return append(bytes, 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]uint8) []byte {
141 bytes = append(bytes, encode_domain(bytes, soa.MName, offsets)...)
142 bytes = append(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]uint8) []byte {
167 return append(bytes, 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]uint8) []byte {
185 return append(bytes, 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]uint8) []byte {
203 return append(bytes, 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]uint8) []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]uint8) []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]uint8) []byte {
272 return append(bytes, 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]uint8) []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]uint8) []byte {
323 bytes = append(bytes, encode_domain(bytes, minfo.RMailBx, offsets)...)
324 bytes = append(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]uint8) []byte {
349 bytes = binary.BigEndian.AppendUint16(bytes, mx.Preference)
350 bytes = append(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]uint8) []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]uint8) []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]uint8) []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 second_dinner := make([]byte, len(bytes))
480 copy(second_dinner, bytes)
481 start := len(second_dinner)
482 second_dinner = r.RData.Encode(second_dinner, offsets)
483 end := len(second_dinner)
484 data := second_dinner[start:end]
485
486 bytes = binary.BigEndian.AppendUint16(bytes, uint16(end-start))
487 bytes = append(bytes, data...)
488
489 return bytes
490}