format.go (2454B)
1 package dns 2 3 import ( 4 "net" 5 "reflect" 6 "strconv" 7 ) 8 9 // NumField returns the number of rdata fields r has. 10 func 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. 18 func Field(r RR, i int) string { 19 if i == 0 { 20 return "" 21 } 22 d := reflect.ValueOf(r).Elem().Field(i) 23 switch d.Kind() { 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.IPv4len { 35 return "" 36 } 37 if d.Len() < net.IPv6len { 38 return net.IPv4(byte(d.Index(0).Uint()), 39 byte(d.Index(1).Uint()), 40 byte(d.Index(2).Uint()), 41 byte(d.Index(3).Uint())).String() 42 } 43 return net.IPv4(byte(d.Index(12).Uint()), 44 byte(d.Index(13).Uint()), 45 byte(d.Index(14).Uint()), 46 byte(d.Index(15).Uint())).String() 47 case `dns:"aaaa"`: 48 if d.Len() < net.IPv6len { 49 return "" 50 } 51 return net.IP{ 52 byte(d.Index(0).Uint()), 53 byte(d.Index(1).Uint()), 54 byte(d.Index(2).Uint()), 55 byte(d.Index(3).Uint()), 56 byte(d.Index(4).Uint()), 57 byte(d.Index(5).Uint()), 58 byte(d.Index(6).Uint()), 59 byte(d.Index(7).Uint()), 60 byte(d.Index(8).Uint()), 61 byte(d.Index(9).Uint()), 62 byte(d.Index(10).Uint()), 63 byte(d.Index(11).Uint()), 64 byte(d.Index(12).Uint()), 65 byte(d.Index(13).Uint()), 66 byte(d.Index(14).Uint()), 67 byte(d.Index(15).Uint()), 68 }.String() 69 case `dns:"nsec"`: 70 if d.Len() == 0 { 71 return "" 72 } 73 s := Type(d.Index(0).Uint()).String() 74 for i := 1; i < d.Len(); i++ { 75 s += " " + Type(d.Index(i).Uint()).String() 76 } 77 return s 78 default: 79 // if it does not have a tag its a string slice 80 fallthrough 81 case `dns:"txt"`: 82 if d.Len() == 0 { 83 return "" 84 } 85 s := d.Index(0).String() 86 for i := 1; i < d.Len(); i++ { 87 s += " " + d.Index(i).String() 88 } 89 return s 90 } 91 } 92 return "" 93 }