QuietTextFormat.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright (c) 2013-2014 by Farsight Security, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package dnstap
  17. import (
  18. "bytes"
  19. "fmt"
  20. "net"
  21. "strconv"
  22. "time"
  23. "github.com/miekg/dns"
  24. )
  25. const quietTimeFormat = "15:04:05"
  26. func textConvertTime(s *bytes.Buffer, secs *uint64, nsecs *uint32) {
  27. if secs != nil {
  28. s.WriteString(time.Unix(int64(*secs), 0).Format(quietTimeFormat))
  29. } else {
  30. s.WriteString("??:??:??")
  31. }
  32. if nsecs != nil {
  33. s.WriteString(fmt.Sprintf(".%06d", *nsecs/1000))
  34. } else {
  35. s.WriteString(".??????")
  36. }
  37. }
  38. func textConvertIP(s *bytes.Buffer, ip []byte) {
  39. if ip != nil {
  40. s.WriteString(net.IP(ip).String())
  41. } else {
  42. s.WriteString("MISSING_ADDRESS")
  43. }
  44. }
  45. func textConvertMessage(m *Message, s *bytes.Buffer) {
  46. isQuery := false
  47. printQueryAddress := false
  48. switch *m.Type {
  49. case Message_CLIENT_QUERY,
  50. Message_RESOLVER_QUERY,
  51. Message_AUTH_QUERY,
  52. Message_FORWARDER_QUERY,
  53. Message_TOOL_QUERY,
  54. Message_UPDATE_QUERY:
  55. isQuery = true
  56. case Message_CLIENT_RESPONSE,
  57. Message_RESOLVER_RESPONSE,
  58. Message_AUTH_RESPONSE,
  59. Message_FORWARDER_RESPONSE,
  60. Message_TOOL_RESPONSE,
  61. Message_UPDATE_RESPONSE:
  62. isQuery = false
  63. default:
  64. s.WriteString("[unhandled Message.Type]\n")
  65. return
  66. }
  67. if isQuery {
  68. textConvertTime(s, m.QueryTimeSec, m.QueryTimeNsec)
  69. } else {
  70. textConvertTime(s, m.ResponseTimeSec, m.ResponseTimeNsec)
  71. }
  72. s.WriteString(" ")
  73. switch *m.Type {
  74. case Message_CLIENT_QUERY,
  75. Message_CLIENT_RESPONSE:
  76. {
  77. s.WriteString("C")
  78. }
  79. case Message_RESOLVER_QUERY,
  80. Message_RESOLVER_RESPONSE:
  81. {
  82. s.WriteString("R")
  83. }
  84. case Message_AUTH_QUERY,
  85. Message_AUTH_RESPONSE:
  86. {
  87. s.WriteString("A")
  88. }
  89. case Message_FORWARDER_QUERY,
  90. Message_FORWARDER_RESPONSE:
  91. {
  92. s.WriteString("F")
  93. }
  94. case Message_STUB_QUERY,
  95. Message_STUB_RESPONSE:
  96. {
  97. s.WriteString("S")
  98. }
  99. case Message_TOOL_QUERY,
  100. Message_TOOL_RESPONSE:
  101. {
  102. s.WriteString("T")
  103. }
  104. case Message_UPDATE_QUERY,
  105. Message_UPDATE_RESPONSE:
  106. {
  107. s.WriteString("U")
  108. }
  109. }
  110. if isQuery {
  111. s.WriteString("Q ")
  112. } else {
  113. s.WriteString("R ")
  114. }
  115. switch *m.Type {
  116. case Message_CLIENT_QUERY,
  117. Message_CLIENT_RESPONSE,
  118. Message_AUTH_QUERY,
  119. Message_AUTH_RESPONSE:
  120. printQueryAddress = true
  121. }
  122. if printQueryAddress {
  123. textConvertIP(s, m.QueryAddress)
  124. } else {
  125. textConvertIP(s, m.ResponseAddress)
  126. }
  127. s.WriteString(" ")
  128. if m.SocketProtocol != nil {
  129. s.WriteString(m.SocketProtocol.String())
  130. }
  131. s.WriteString(" ")
  132. var err error
  133. msg := new(dns.Msg)
  134. if isQuery {
  135. s.WriteString(strconv.Itoa(len(m.QueryMessage)))
  136. s.WriteString("b ")
  137. err = msg.Unpack(m.QueryMessage)
  138. } else {
  139. s.WriteString(strconv.Itoa(len(m.ResponseMessage)))
  140. s.WriteString("b ")
  141. err = msg.Unpack(m.ResponseMessage)
  142. }
  143. if err != nil || len(msg.Question) == 0 {
  144. s.WriteString("X ")
  145. } else {
  146. s.WriteString("\"" + msg.Question[0].Name + "\" ")
  147. s.WriteString(dns.Class(msg.Question[0].Qclass).String() + " ")
  148. s.WriteString(dns.Type(msg.Question[0].Qtype).String())
  149. }
  150. s.WriteString("\n")
  151. }
  152. // TextFormat renders a dnstap message in a compact human-readable text
  153. // form.
  154. func TextFormat(dt *Dnstap) (out []byte, ok bool) {
  155. var s bytes.Buffer
  156. if *dt.Type == Dnstap_MESSAGE {
  157. textConvertMessage(dt.Message, &s)
  158. return s.Bytes(), true
  159. }
  160. return nil, false
  161. }