1package dns 2 3import ( 4 "net" 5 "reflect" 6 "strconv" 7) 8 9// NumField returns the number of rdata fields r has. 10func NumField(r RR) int { 11 return reflect.ValueOf(r).Elem().NumField() - 1 // Remove RR_Header 12} 13 14// Field returns the rdata field i as a string. Fields are indexed starting from 1. 15// RR types that holds slice data, for instance the NSEC type bitmap will return a single 16// string where the types are concatenated using a space. 17// Accessing non existing fields will cause a panic. 18func Field(r RR, i int) string { 19 if i == 0 { 20 return "" 21 } 22 d := reflect.ValueOf(r).Elem().Field(i) 23 switch k := d.Kind(); k { 24 case reflect.String: 25 return d.String() 26 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 27 return strconv.FormatInt(d.Int(), 10) 28 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 29 return strconv.FormatUint(d.Uint(), 10) 30 case reflect.Slice: 31 switch reflect.ValueOf(r).Elem().Type().Field(i).Tag { 32 case `dns:"a"`: 33 // TODO(miek): Hmm store this as 16 bytes 34 if d.Len() < net.IPv6len { 35 return net.IPv4(byte(d.Index(0).Uint()), 36 byte(d.Index(1).Uint()), 37 byte(d.Index(2).Uint()), 38 byte(d.Index(3).Uint())).String() 39 } 40 return net.IPv4(byte(d.Index(12).Uint()), 41 byte(d.Index(13).Uint()), 42 byte(d.Index(14).Uint()), 43 byte(d.Index(15).Uint())).String() 44 case `dns:"aaaa"`: 45 return net.IP{ 46 byte(d.Index(0).Uint()), 47 byte(d.Index(1).Uint()), 48 byte(d.Index(2).Uint()), 49 byte(d.Index(3).Uint()), 50 byte(d.Index(4).Uint()), 51 byte(d.Index(5).Uint()), 52 byte(d.Index(6).Uint()), 53 byte(d.Index(7).Uint()), 54 byte(d.Index(8).Uint()), 55 byte(d.Index(9).Uint()), 56 byte(d.Index(10).Uint()), 57 byte(d.Index(11).Uint()), 58 byte(d.Index(12).Uint()), 59 byte(d.Index(13).Uint()), 60 byte(d.Index(14).Uint()), 61 byte(d.Index(15).Uint()), 62 }.String() 63 case `dns:"nsec"`: 64 if d.Len() == 0 { 65 return "" 66 } 67 s := Type(d.Index(0).Uint()).String() 68 for i := 1; i < d.Len(); i++ { 69 s += " " + Type(d.Index(i).Uint()).String() 70 } 71 return s 72 default: 73 // if it does not have a tag its a string slice 74 fallthrough 75 case `dns:"txt"`: 76 if d.Len() == 0 { 77 return "" 78 } 79 s := d.Index(0).String() 80 for i := 1; i < d.Len(); i++ { 81 s += " " + d.Index(i).String() 82 } 83 return s 84 } 85 } 86 return "" 87} 88