format.go 2.5 KB

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