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