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}