a go dns packet parser
at main 9.3 kB view raw
1package magna 2 3import ( 4 "fmt" 5 "net" 6) 7 8type ( 9 // An OPCode specifies the kind of query. 10 OPCode int 11 12 // A RCode specifies the response code. 13 RCode int 14 15 // A DNSType specifies the type of the query. 16 DNSType uint16 17 18 // A DNSClass specifies the class of the query. 19 DNSClass uint16 20) 21 22const ( 23 QUERY OPCode = iota 24 IQUERY 25 STATUS 26) 27 28func (op OPCode) String() string { 29 switch op { 30 case QUERY: 31 return "QUERY" 32 case IQUERY: 33 return "IQUERY" 34 case STATUS: 35 return "STATUS" 36 default: 37 return fmt.Sprintf("RESERVED(%d)", int(op)) 38 } 39} 40 41const ( 42 NOERROR RCode = iota 43 FORMERR 44 SERVFAIL 45 NXDOMAIN 46 NOTIMP 47 REFUSED 48 49 BADVERS = 16 50) 51 52func (r RCode) String() string { 53 switch r { 54 case NOERROR: 55 return "NOERROR" 56 case FORMERR: 57 return "FORMERR" 58 case SERVFAIL: 59 return "SERVFAIL" 60 case NXDOMAIN: 61 return "NXDOMAIN" 62 case NOTIMP: 63 return "NOTIMP" 64 case REFUSED: 65 return "REFUSED" 66 case BADVERS: 67 return "BADVERS" 68 default: 69 return fmt.Sprintf("RESERVED(%d)", int(r)) 70 } 71} 72 73const ( 74 AType DNSType = 1 75 NSType = 2 76 MDType = 3 77 MFType = 4 78 CNAMEType = 5 79 SOAType = 6 80 MBType = 7 81 MGType = 8 82 MRType = 9 83 NULLType = 10 84 WKSType = 11 85 PTRType = 12 86 HINFOType = 13 87 MINFOType = 14 88 MXType = 15 89 TXTType = 16 90 RPType = 17 91 AFSDBType = 18 92 X25Type = 19 93 ISDNType = 20 94 RTType = 21 95 AAAAType = 28 96 97 OPTType = 41 98 99 AXFRType = 252 100 MAILBType = 253 101 MAILAType = 254 102 AllType = 255 103) 104 105func (t DNSType) String() string { 106 switch t { 107 case AType: 108 return "A" 109 case NSType: 110 return "NS" 111 case MDType: 112 return "MD" 113 case MFType: 114 return "MF" 115 case CNAMEType: 116 return "CNAME" 117 case SOAType: 118 return "SOA" 119 case MBType: 120 return "MB" 121 case MGType: 122 return "MG" 123 case MRType: 124 return "MR" 125 case NULLType: 126 return "NULL" 127 case WKSType: 128 return "WKS" 129 case PTRType: 130 return "PTR" 131 case HINFOType: 132 return "HINFO" 133 case MINFOType: 134 return "MINFO" 135 case MXType: 136 return "MX" 137 case TXTType: 138 return "TXT" 139 case AFSDBType: 140 return "AFSDB" 141 case RPType: 142 return "RP" 143 case X25Type: 144 return "X25" 145 case ISDNType: 146 return "ISDN" 147 case RTType: 148 return "RT" 149 case AAAAType: 150 return "AAAA" 151 case OPTType: 152 return "OPT" 153 case AXFRType: 154 return "AXFR" 155 case MAILBType: 156 return "MAILB" 157 case MAILAType: 158 return "MAILA" 159 case AllType: 160 return "All" 161 default: 162 return fmt.Sprintf("RESERVED(%d)", int(t)) 163 } 164} 165 166const ( 167 IN DNSClass = iota + 1 168 CS 169 CH 170 HS 171 172 ANY = 255 173) 174 175func (c DNSClass) String() string { 176 switch c { 177 case IN: 178 return "IN" 179 case CS: 180 return "CS" 181 case CH: 182 return "CH" 183 case HS: 184 return "HS" 185 case ANY: 186 return "*" 187 default: 188 return fmt.Sprintf("RESERVED(%d)", int(c)) 189 } 190} 191 192// A Message represents the single format supported by the DNS protocol. 193type Message struct { 194 Header Header // Header contains metadata about the message. 195 Question []Question // Question contains a slice of questions. 196 Answer []ResourceRecord // Answer contains a slice of resource records. 197 Authority []ResourceRecord // Authority contains a slice of resource records. 198 Additional []ResourceRecord // Additional contains a slice of resource records. 199 200 // EDNS information 201 HasEDNS bool // If the DNS message detected EDNS 202 ExtendedRCode uint8 // first 8 bits to use if edns. 203 EDNSVersion uint8 // EDNS version of sender. 204 EDNSFlags uint16 // EDNS specific flag. 205 EDNSOptions []EDNSOption // EDNS options. 206 UDPSize uint16 // Max UDP size of sender. 207 208 // offsets is a map of domains pointing to the seen offset used 209 // in domain compression. 210 offsets map[string]uint16 211} 212 213// A Header represents the metadata information of a DNS packet. 214type Header struct { 215 ID uint16 // ID is a 16 bit identifier. 216 QR bool // QR (query response) specifies if the packet is a query (false) or response (true). 217 OPCode OPCode // OPCode is a 4bit value that specifies the kind of the query. 218 AA bool // AA (Authoritative Answer) specifies if the responding name server is the authoritative server. 219 TC bool // TC (Truncation) specifies if the packet was truncated due to length. 220 RD bool // RD (Recursion Desired) specifies that the client wants to recurse. 221 RA bool // RA (Recursion Available) specifies that the server is available to recurse. 222 Z uint8 // Z Reserved for future use 223 RCode RCode // RCode is a 4 bit field representing the response error. 224 QDCount uint16 // QDCount specifies number of entries in the Question slice. 225 ANCount uint16 // ANCount specifies number of entries in the Answer slice. 226 NSCount uint16 // NSCount specifies number of entries in the Authority slice. 227 ARCount uint16 // ARCount specifies number of entries in the Additional slice. 228} 229 230// A Question represent a question in the DNS packet. 231type Question struct { 232 QName string // QName domain name being questioned. 233 QType DNSType // QType specifies the type of the question. 234 QClass DNSClass // QClass specifies the class of the question. 235} 236 237// A ResourceRecordData represents the RDATA field of the resource record. 238// Decode: 239// 240// []byte - DNS packet 241// int - offset in []byte to start parsing resource record data 242// int - length of the resource record field 243// 244// Encode: 245// 246// []byte - DNS Packet 247// *map[string]uint8 - map containing labels and offsets for domain name compression 248type ResourceRecordData interface { 249 Decode([]byte, int, int) (int, error) 250 Encode([]byte, *map[string]uint16) ([]byte, error) 251 String() string 252} 253 254// ResourceRecord represents DNS records. 255type ResourceRecord struct { 256 Name string // a domain label 257 RType DNSType // the type of the record 258 RClass DNSClass // the class of the record 259 TTL uint32 // the time to live of the record in seconds 260 RDLength uint16 // the length of the record in number of bytes 261 RData ResourceRecordData // the data of the record 262} 263 264// A represents a 32 bit Internet Address. 265type A struct { 266 Address net.IP 267} 268 269// NS represents 270type NS struct { 271 NSDName string 272} 273 274// MD represents the mail agent for a domain. 275// XXX: Obsolete 276type MD struct { 277 MADName string 278} 279 280// MF represents a host which has a mail agent for a domain. 281// XXX: Obsolete 282type MF struct { 283 MADName string 284} 285 286// CNAME represents the canonical name for the owner. 287type CNAME struct { 288 CName string 289} 290 291// SOA represents 292type SOA struct { 293 MName string // MName represents the name server that was the original source of data for a zone. 294 RName string // RName represents a mailbox of the person responsible for this zone. 295 Serial uint32 // Serial is a 32 bit version number of the original copy of the zone. 296 Refresh uint32 // Refresh is a 32 bit time interval before the zone should be refreshed. 297 Retry uint32 // Retry is a 32 bit time interval that should elapse before a failed refresh is retried. 298 Expire uint32 // Expire is the upper limit on the time interval that can elapse before the zone is no longer authoritative. 299 Minimum uint32 // Minimum is the minimum TTL field that should be exported with any RR from this zone. 300} 301 302// MB represents the host with a specified mailbox. 303type MB struct { 304 MADName string 305} 306 307// MG represents a mailbox which is configured for MGMName. 308type MG struct { 309 MGMName string 310} 311 312// MR specifies the proper rename of a mailbox. 313type MR struct { 314 NEWName string 315} 316 317// NULL can be anything as long as its under 65535 octets. 318type NULL struct { 319 Anything []byte 320} 321 322// WKS specifies well known services supported by a protocol. 323type WKS struct { 324 Address net.IP // Address is a 32 bit Internet address. 325 Protocol uint8 // Protocol is a 8 bit IP protocol number. 326 BitMap []byte // BitMap is a variable length bit map must be multiple of 8 bits. 327} 328 329// PTR specifies to a location in the domain name space. 330type PTR struct { 331 PTRDName string 332} 333 334// HINFO represents the general information about a server. 335type HINFO struct { 336 CPU string // CPU specifies the CPU type. 337 OS string // OS specifies the operating system. 338} 339 340// MINFO represents mailing list information. 341type MINFO struct { 342 RMailBx string // RMailBx specifies the mailbox for a mailing list. 343 EMailBx string // EMailBx specifes a mailbox for receiving errors. 344} 345 346// MX represents a host acting as a mail exchange. 347type MX struct { 348 Preference uint16 // Preference specifies the preference with lower values being prefered. 349 Exchange string // Exchange specifies host acting for the name. 350} 351 352// TXT represents one or more character strings. 353type TXT struct { 354 TxtData []string 355} 356 357type AFSDB struct { 358 Subtype uint16 359 Hostname string 360} 361 362type RP struct { 363 MBoxDName string 364 TXTDName string 365} 366 367type X25 struct { 368 PSDNAddress string 369} 370 371type ISDN struct { 372 ISDNAddress string 373 Subaddress string 374} 375 376type RT struct { 377 Preference uint16 378 IntermediateHost string 379} 380 381type AAAA struct { 382 Address net.IP 383} 384 385type EDNSOption struct { 386 Code uint16 387 Data []byte 388} 389 390type OPT struct { 391 Options []EDNSOption 392} 393 394// Reserved represents a record that is not yet implemented. 395type Reserved struct { 396 Bytes []byte 397}