David K. Bainbridge | 215e024 | 2017-09-05 23:18:24 -0700 | [diff] [blame] | 1 | // Copyright 2009 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | // Package dnsmessage provides a mostly RFC 1035 compliant implementation of |
| 6 | // DNS message packing and unpacking. |
| 7 | // |
| 8 | // This implementation is designed to minimize heap allocations and avoid |
| 9 | // unnecessary packing and unpacking as much as possible. |
| 10 | package dnsmessage |
| 11 | |
| 12 | import ( |
| 13 | "errors" |
| 14 | ) |
| 15 | |
| 16 | // Packet formats |
| 17 | |
| 18 | // A Type is a type of DNS request and response. |
| 19 | type Type uint16 |
| 20 | |
| 21 | // A Class is a type of network. |
| 22 | type Class uint16 |
| 23 | |
| 24 | // An OpCode is a DNS operation code. |
| 25 | type OpCode uint16 |
| 26 | |
| 27 | // An RCode is a DNS response status code. |
| 28 | type RCode uint16 |
| 29 | |
| 30 | // Wire constants. |
| 31 | const ( |
| 32 | // ResourceHeader.Type and Question.Type |
| 33 | TypeA Type = 1 |
| 34 | TypeNS Type = 2 |
| 35 | TypeCNAME Type = 5 |
| 36 | TypeSOA Type = 6 |
| 37 | TypePTR Type = 12 |
| 38 | TypeMX Type = 15 |
| 39 | TypeTXT Type = 16 |
| 40 | TypeAAAA Type = 28 |
| 41 | TypeSRV Type = 33 |
| 42 | |
| 43 | // Question.Type |
| 44 | TypeWKS Type = 11 |
| 45 | TypeHINFO Type = 13 |
| 46 | TypeMINFO Type = 14 |
| 47 | TypeAXFR Type = 252 |
| 48 | TypeALL Type = 255 |
| 49 | |
| 50 | // ResourceHeader.Class and Question.Class |
| 51 | ClassINET Class = 1 |
| 52 | ClassCSNET Class = 2 |
| 53 | ClassCHAOS Class = 3 |
| 54 | ClassHESIOD Class = 4 |
| 55 | |
| 56 | // Question.Class |
| 57 | ClassANY Class = 255 |
| 58 | |
| 59 | // Message.Rcode |
| 60 | RCodeSuccess RCode = 0 |
| 61 | RCodeFormatError RCode = 1 |
| 62 | RCodeServerFailure RCode = 2 |
| 63 | RCodeNameError RCode = 3 |
| 64 | RCodeNotImplemented RCode = 4 |
| 65 | RCodeRefused RCode = 5 |
| 66 | ) |
| 67 | |
| 68 | var ( |
| 69 | // ErrNotStarted indicates that the prerequisite information isn't |
| 70 | // available yet because the previous records haven't been appropriately |
| 71 | // parsed, skipped or finished. |
| 72 | ErrNotStarted = errors.New("parsing/packing of this type isn't available yet") |
| 73 | |
| 74 | // ErrSectionDone indicated that all records in the section have been |
| 75 | // parsed or finished. |
| 76 | ErrSectionDone = errors.New("parsing/packing of this section has completed") |
| 77 | |
| 78 | errBaseLen = errors.New("insufficient data for base length type") |
| 79 | errCalcLen = errors.New("insufficient data for calculated length type") |
| 80 | errReserved = errors.New("segment prefix is reserved") |
| 81 | errTooManyPtr = errors.New("too many pointers (>10)") |
| 82 | errInvalidPtr = errors.New("invalid pointer") |
| 83 | errNilResouceBody = errors.New("nil resource body") |
| 84 | errResourceLen = errors.New("insufficient data for resource body length") |
| 85 | errSegTooLong = errors.New("segment length too long") |
| 86 | errZeroSegLen = errors.New("zero length segment") |
| 87 | errResTooLong = errors.New("resource length too long") |
| 88 | errTooManyQuestions = errors.New("too many Questions to pack (>65535)") |
| 89 | errTooManyAnswers = errors.New("too many Answers to pack (>65535)") |
| 90 | errTooManyAuthorities = errors.New("too many Authorities to pack (>65535)") |
| 91 | errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)") |
| 92 | errNonCanonicalName = errors.New("name is not in canonical format (it must end with a .)") |
| 93 | ) |
| 94 | |
| 95 | // Internal constants. |
| 96 | const ( |
| 97 | // packStartingCap is the default initial buffer size allocated during |
| 98 | // packing. |
| 99 | // |
| 100 | // The starting capacity doesn't matter too much, but most DNS responses |
| 101 | // Will be <= 512 bytes as it is the limit for DNS over UDP. |
| 102 | packStartingCap = 512 |
| 103 | |
| 104 | // uint16Len is the length (in bytes) of a uint16. |
| 105 | uint16Len = 2 |
| 106 | |
| 107 | // uint32Len is the length (in bytes) of a uint32. |
| 108 | uint32Len = 4 |
| 109 | |
| 110 | // headerLen is the length (in bytes) of a DNS header. |
| 111 | // |
| 112 | // A header is comprised of 6 uint16s and no padding. |
| 113 | headerLen = 6 * uint16Len |
| 114 | ) |
| 115 | |
| 116 | type nestedError struct { |
| 117 | // s is the current level's error message. |
| 118 | s string |
| 119 | |
| 120 | // err is the nested error. |
| 121 | err error |
| 122 | } |
| 123 | |
| 124 | // nestedError implements error.Error. |
| 125 | func (e *nestedError) Error() string { |
| 126 | return e.s + ": " + e.err.Error() |
| 127 | } |
| 128 | |
| 129 | // Header is a representation of a DNS message header. |
| 130 | type Header struct { |
| 131 | ID uint16 |
| 132 | Response bool |
| 133 | OpCode OpCode |
| 134 | Authoritative bool |
| 135 | Truncated bool |
| 136 | RecursionDesired bool |
| 137 | RecursionAvailable bool |
| 138 | RCode RCode |
| 139 | } |
| 140 | |
| 141 | func (m *Header) pack() (id uint16, bits uint16) { |
| 142 | id = m.ID |
| 143 | bits = uint16(m.OpCode)<<11 | uint16(m.RCode) |
| 144 | if m.RecursionAvailable { |
| 145 | bits |= headerBitRA |
| 146 | } |
| 147 | if m.RecursionDesired { |
| 148 | bits |= headerBitRD |
| 149 | } |
| 150 | if m.Truncated { |
| 151 | bits |= headerBitTC |
| 152 | } |
| 153 | if m.Authoritative { |
| 154 | bits |= headerBitAA |
| 155 | } |
| 156 | if m.Response { |
| 157 | bits |= headerBitQR |
| 158 | } |
| 159 | return |
| 160 | } |
| 161 | |
| 162 | // Message is a representation of a DNS message. |
| 163 | type Message struct { |
| 164 | Header |
| 165 | Questions []Question |
| 166 | Answers []Resource |
| 167 | Authorities []Resource |
| 168 | Additionals []Resource |
| 169 | } |
| 170 | |
| 171 | type section uint8 |
| 172 | |
| 173 | const ( |
| 174 | sectionNotStarted section = iota |
| 175 | sectionHeader |
| 176 | sectionQuestions |
| 177 | sectionAnswers |
| 178 | sectionAuthorities |
| 179 | sectionAdditionals |
| 180 | sectionDone |
| 181 | |
| 182 | headerBitQR = 1 << 15 // query/response (response=1) |
| 183 | headerBitAA = 1 << 10 // authoritative |
| 184 | headerBitTC = 1 << 9 // truncated |
| 185 | headerBitRD = 1 << 8 // recursion desired |
| 186 | headerBitRA = 1 << 7 // recursion available |
| 187 | ) |
| 188 | |
| 189 | var sectionNames = map[section]string{ |
| 190 | sectionHeader: "header", |
| 191 | sectionQuestions: "Question", |
| 192 | sectionAnswers: "Answer", |
| 193 | sectionAuthorities: "Authority", |
| 194 | sectionAdditionals: "Additional", |
| 195 | } |
| 196 | |
| 197 | // header is the wire format for a DNS message header. |
| 198 | type header struct { |
| 199 | id uint16 |
| 200 | bits uint16 |
| 201 | questions uint16 |
| 202 | answers uint16 |
| 203 | authorities uint16 |
| 204 | additionals uint16 |
| 205 | } |
| 206 | |
| 207 | func (h *header) count(sec section) uint16 { |
| 208 | switch sec { |
| 209 | case sectionQuestions: |
| 210 | return h.questions |
| 211 | case sectionAnswers: |
| 212 | return h.answers |
| 213 | case sectionAuthorities: |
| 214 | return h.authorities |
| 215 | case sectionAdditionals: |
| 216 | return h.additionals |
| 217 | } |
| 218 | return 0 |
| 219 | } |
| 220 | |
| 221 | func (h *header) pack(msg []byte) []byte { |
| 222 | msg = packUint16(msg, h.id) |
| 223 | msg = packUint16(msg, h.bits) |
| 224 | msg = packUint16(msg, h.questions) |
| 225 | msg = packUint16(msg, h.answers) |
| 226 | msg = packUint16(msg, h.authorities) |
| 227 | return packUint16(msg, h.additionals) |
| 228 | } |
| 229 | |
| 230 | func (h *header) unpack(msg []byte, off int) (int, error) { |
| 231 | newOff := off |
| 232 | var err error |
| 233 | if h.id, newOff, err = unpackUint16(msg, newOff); err != nil { |
| 234 | return off, &nestedError{"id", err} |
| 235 | } |
| 236 | if h.bits, newOff, err = unpackUint16(msg, newOff); err != nil { |
| 237 | return off, &nestedError{"bits", err} |
| 238 | } |
| 239 | if h.questions, newOff, err = unpackUint16(msg, newOff); err != nil { |
| 240 | return off, &nestedError{"questions", err} |
| 241 | } |
| 242 | if h.answers, newOff, err = unpackUint16(msg, newOff); err != nil { |
| 243 | return off, &nestedError{"answers", err} |
| 244 | } |
| 245 | if h.authorities, newOff, err = unpackUint16(msg, newOff); err != nil { |
| 246 | return off, &nestedError{"authorities", err} |
| 247 | } |
| 248 | if h.additionals, newOff, err = unpackUint16(msg, newOff); err != nil { |
| 249 | return off, &nestedError{"additionals", err} |
| 250 | } |
| 251 | return newOff, nil |
| 252 | } |
| 253 | |
| 254 | func (h *header) header() Header { |
| 255 | return Header{ |
| 256 | ID: h.id, |
| 257 | Response: (h.bits & headerBitQR) != 0, |
| 258 | OpCode: OpCode(h.bits>>11) & 0xF, |
| 259 | Authoritative: (h.bits & headerBitAA) != 0, |
| 260 | Truncated: (h.bits & headerBitTC) != 0, |
| 261 | RecursionDesired: (h.bits & headerBitRD) != 0, |
| 262 | RecursionAvailable: (h.bits & headerBitRA) != 0, |
| 263 | RCode: RCode(h.bits & 0xF), |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | // A Resource is a DNS resource record. |
| 268 | type Resource struct { |
| 269 | Header ResourceHeader |
| 270 | Body ResourceBody |
| 271 | } |
| 272 | |
| 273 | // A ResourceBody is a DNS resource record minus the header. |
| 274 | type ResourceBody interface { |
| 275 | // pack packs a Resource except for its header. |
| 276 | pack(msg []byte, compression map[string]int) ([]byte, error) |
| 277 | |
| 278 | // realType returns the actual type of the Resource. This is used to |
| 279 | // fill in the header Type field. |
| 280 | realType() Type |
| 281 | } |
| 282 | |
| 283 | func (r *Resource) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 284 | if r.Body == nil { |
| 285 | return msg, errNilResouceBody |
| 286 | } |
| 287 | oldMsg := msg |
| 288 | r.Header.Type = r.Body.realType() |
| 289 | msg, length, err := r.Header.pack(msg, compression) |
| 290 | if err != nil { |
| 291 | return msg, &nestedError{"ResourceHeader", err} |
| 292 | } |
| 293 | preLen := len(msg) |
| 294 | msg, err = r.Body.pack(msg, compression) |
| 295 | if err != nil { |
| 296 | return msg, &nestedError{"content", err} |
| 297 | } |
| 298 | if err := r.Header.fixLen(msg, length, preLen); err != nil { |
| 299 | return oldMsg, err |
| 300 | } |
| 301 | return msg, nil |
| 302 | } |
| 303 | |
| 304 | // A Parser allows incrementally parsing a DNS message. |
| 305 | // |
| 306 | // When parsing is started, the Header is parsed. Next, each Question can be |
| 307 | // either parsed or skipped. Alternatively, all Questions can be skipped at |
| 308 | // once. When all Questions have been parsed, attempting to parse Questions |
| 309 | // will return (nil, nil) and attempting to skip Questions will return |
| 310 | // (true, nil). After all Questions have been either parsed or skipped, all |
| 311 | // Answers, Authorities and Additionals can be either parsed or skipped in the |
| 312 | // same way, and each type of Resource must be fully parsed or skipped before |
| 313 | // proceeding to the next type of Resource. |
| 314 | // |
| 315 | // Note that there is no requirement to fully skip or parse the message. |
| 316 | type Parser struct { |
| 317 | msg []byte |
| 318 | header header |
| 319 | |
| 320 | section section |
| 321 | off int |
| 322 | index int |
| 323 | resHeaderValid bool |
| 324 | resHeader ResourceHeader |
| 325 | } |
| 326 | |
| 327 | // Start parses the header and enables the parsing of Questions. |
| 328 | func (p *Parser) Start(msg []byte) (Header, error) { |
| 329 | if p.msg != nil { |
| 330 | *p = Parser{} |
| 331 | } |
| 332 | p.msg = msg |
| 333 | var err error |
| 334 | if p.off, err = p.header.unpack(msg, 0); err != nil { |
| 335 | return Header{}, &nestedError{"unpacking header", err} |
| 336 | } |
| 337 | p.section = sectionQuestions |
| 338 | return p.header.header(), nil |
| 339 | } |
| 340 | |
| 341 | func (p *Parser) checkAdvance(sec section) error { |
| 342 | if p.section < sec { |
| 343 | return ErrNotStarted |
| 344 | } |
| 345 | if p.section > sec { |
| 346 | return ErrSectionDone |
| 347 | } |
| 348 | p.resHeaderValid = false |
| 349 | if p.index == int(p.header.count(sec)) { |
| 350 | p.index = 0 |
| 351 | p.section++ |
| 352 | return ErrSectionDone |
| 353 | } |
| 354 | return nil |
| 355 | } |
| 356 | |
| 357 | func (p *Parser) resource(sec section) (Resource, error) { |
| 358 | var r Resource |
| 359 | var err error |
| 360 | r.Header, err = p.resourceHeader(sec) |
| 361 | if err != nil { |
| 362 | return r, err |
| 363 | } |
| 364 | p.resHeaderValid = false |
| 365 | r.Body, p.off, err = unpackResourceBody(p.msg, p.off, r.Header) |
| 366 | if err != nil { |
| 367 | return Resource{}, &nestedError{"unpacking " + sectionNames[sec], err} |
| 368 | } |
| 369 | p.index++ |
| 370 | return r, nil |
| 371 | } |
| 372 | |
| 373 | func (p *Parser) resourceHeader(sec section) (ResourceHeader, error) { |
| 374 | if p.resHeaderValid { |
| 375 | return p.resHeader, nil |
| 376 | } |
| 377 | if err := p.checkAdvance(sec); err != nil { |
| 378 | return ResourceHeader{}, err |
| 379 | } |
| 380 | var hdr ResourceHeader |
| 381 | off, err := hdr.unpack(p.msg, p.off) |
| 382 | if err != nil { |
| 383 | return ResourceHeader{}, err |
| 384 | } |
| 385 | p.resHeaderValid = true |
| 386 | p.resHeader = hdr |
| 387 | p.off = off |
| 388 | return hdr, nil |
| 389 | } |
| 390 | |
| 391 | func (p *Parser) skipResource(sec section) error { |
| 392 | if p.resHeaderValid { |
| 393 | newOff := p.off + int(p.resHeader.Length) |
| 394 | if newOff > len(p.msg) { |
| 395 | return errResourceLen |
| 396 | } |
| 397 | p.off = newOff |
| 398 | p.resHeaderValid = false |
| 399 | p.index++ |
| 400 | return nil |
| 401 | } |
| 402 | if err := p.checkAdvance(sec); err != nil { |
| 403 | return err |
| 404 | } |
| 405 | var err error |
| 406 | p.off, err = skipResource(p.msg, p.off) |
| 407 | if err != nil { |
| 408 | return &nestedError{"skipping: " + sectionNames[sec], err} |
| 409 | } |
| 410 | p.index++ |
| 411 | return nil |
| 412 | } |
| 413 | |
| 414 | // Question parses a single Question. |
| 415 | func (p *Parser) Question() (Question, error) { |
| 416 | if err := p.checkAdvance(sectionQuestions); err != nil { |
| 417 | return Question{}, err |
| 418 | } |
| 419 | var name Name |
| 420 | off, err := name.unpack(p.msg, p.off) |
| 421 | if err != nil { |
| 422 | return Question{}, &nestedError{"unpacking Question.Name", err} |
| 423 | } |
| 424 | typ, off, err := unpackType(p.msg, off) |
| 425 | if err != nil { |
| 426 | return Question{}, &nestedError{"unpacking Question.Type", err} |
| 427 | } |
| 428 | class, off, err := unpackClass(p.msg, off) |
| 429 | if err != nil { |
| 430 | return Question{}, &nestedError{"unpacking Question.Class", err} |
| 431 | } |
| 432 | p.off = off |
| 433 | p.index++ |
| 434 | return Question{name, typ, class}, nil |
| 435 | } |
| 436 | |
| 437 | // AllQuestions parses all Questions. |
| 438 | func (p *Parser) AllQuestions() ([]Question, error) { |
| 439 | qs := make([]Question, 0, p.header.questions) |
| 440 | for { |
| 441 | q, err := p.Question() |
| 442 | if err == ErrSectionDone { |
| 443 | return qs, nil |
| 444 | } |
| 445 | if err != nil { |
| 446 | return nil, err |
| 447 | } |
| 448 | qs = append(qs, q) |
| 449 | } |
| 450 | } |
| 451 | |
| 452 | // SkipQuestion skips a single Question. |
| 453 | func (p *Parser) SkipQuestion() error { |
| 454 | if err := p.checkAdvance(sectionQuestions); err != nil { |
| 455 | return err |
| 456 | } |
| 457 | off, err := skipName(p.msg, p.off) |
| 458 | if err != nil { |
| 459 | return &nestedError{"skipping Question Name", err} |
| 460 | } |
| 461 | if off, err = skipType(p.msg, off); err != nil { |
| 462 | return &nestedError{"skipping Question Type", err} |
| 463 | } |
| 464 | if off, err = skipClass(p.msg, off); err != nil { |
| 465 | return &nestedError{"skipping Question Class", err} |
| 466 | } |
| 467 | p.off = off |
| 468 | p.index++ |
| 469 | return nil |
| 470 | } |
| 471 | |
| 472 | // SkipAllQuestions skips all Questions. |
| 473 | func (p *Parser) SkipAllQuestions() error { |
| 474 | for { |
| 475 | if err := p.SkipQuestion(); err == ErrSectionDone { |
| 476 | return nil |
| 477 | } else if err != nil { |
| 478 | return err |
| 479 | } |
| 480 | } |
| 481 | } |
| 482 | |
| 483 | // AnswerHeader parses a single Answer ResourceHeader. |
| 484 | func (p *Parser) AnswerHeader() (ResourceHeader, error) { |
| 485 | return p.resourceHeader(sectionAnswers) |
| 486 | } |
| 487 | |
| 488 | // Answer parses a single Answer Resource. |
| 489 | func (p *Parser) Answer() (Resource, error) { |
| 490 | return p.resource(sectionAnswers) |
| 491 | } |
| 492 | |
| 493 | // AllAnswers parses all Answer Resources. |
| 494 | func (p *Parser) AllAnswers() ([]Resource, error) { |
| 495 | as := make([]Resource, 0, p.header.answers) |
| 496 | for { |
| 497 | a, err := p.Answer() |
| 498 | if err == ErrSectionDone { |
| 499 | return as, nil |
| 500 | } |
| 501 | if err != nil { |
| 502 | return nil, err |
| 503 | } |
| 504 | as = append(as, a) |
| 505 | } |
| 506 | } |
| 507 | |
| 508 | // SkipAnswer skips a single Answer Resource. |
| 509 | func (p *Parser) SkipAnswer() error { |
| 510 | return p.skipResource(sectionAnswers) |
| 511 | } |
| 512 | |
| 513 | // SkipAllAnswers skips all Answer Resources. |
| 514 | func (p *Parser) SkipAllAnswers() error { |
| 515 | for { |
| 516 | if err := p.SkipAnswer(); err == ErrSectionDone { |
| 517 | return nil |
| 518 | } else if err != nil { |
| 519 | return err |
| 520 | } |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | // AuthorityHeader parses a single Authority ResourceHeader. |
| 525 | func (p *Parser) AuthorityHeader() (ResourceHeader, error) { |
| 526 | return p.resourceHeader(sectionAuthorities) |
| 527 | } |
| 528 | |
| 529 | // Authority parses a single Authority Resource. |
| 530 | func (p *Parser) Authority() (Resource, error) { |
| 531 | return p.resource(sectionAuthorities) |
| 532 | } |
| 533 | |
| 534 | // AllAuthorities parses all Authority Resources. |
| 535 | func (p *Parser) AllAuthorities() ([]Resource, error) { |
| 536 | as := make([]Resource, 0, p.header.authorities) |
| 537 | for { |
| 538 | a, err := p.Authority() |
| 539 | if err == ErrSectionDone { |
| 540 | return as, nil |
| 541 | } |
| 542 | if err != nil { |
| 543 | return nil, err |
| 544 | } |
| 545 | as = append(as, a) |
| 546 | } |
| 547 | } |
| 548 | |
| 549 | // SkipAuthority skips a single Authority Resource. |
| 550 | func (p *Parser) SkipAuthority() error { |
| 551 | return p.skipResource(sectionAuthorities) |
| 552 | } |
| 553 | |
| 554 | // SkipAllAuthorities skips all Authority Resources. |
| 555 | func (p *Parser) SkipAllAuthorities() error { |
| 556 | for { |
| 557 | if err := p.SkipAuthority(); err == ErrSectionDone { |
| 558 | return nil |
| 559 | } else if err != nil { |
| 560 | return err |
| 561 | } |
| 562 | } |
| 563 | } |
| 564 | |
| 565 | // AdditionalHeader parses a single Additional ResourceHeader. |
| 566 | func (p *Parser) AdditionalHeader() (ResourceHeader, error) { |
| 567 | return p.resourceHeader(sectionAdditionals) |
| 568 | } |
| 569 | |
| 570 | // Additional parses a single Additional Resource. |
| 571 | func (p *Parser) Additional() (Resource, error) { |
| 572 | return p.resource(sectionAdditionals) |
| 573 | } |
| 574 | |
| 575 | // AllAdditionals parses all Additional Resources. |
| 576 | func (p *Parser) AllAdditionals() ([]Resource, error) { |
| 577 | as := make([]Resource, 0, p.header.additionals) |
| 578 | for { |
| 579 | a, err := p.Additional() |
| 580 | if err == ErrSectionDone { |
| 581 | return as, nil |
| 582 | } |
| 583 | if err != nil { |
| 584 | return nil, err |
| 585 | } |
| 586 | as = append(as, a) |
| 587 | } |
| 588 | } |
| 589 | |
| 590 | // SkipAdditional skips a single Additional Resource. |
| 591 | func (p *Parser) SkipAdditional() error { |
| 592 | return p.skipResource(sectionAdditionals) |
| 593 | } |
| 594 | |
| 595 | // SkipAllAdditionals skips all Additional Resources. |
| 596 | func (p *Parser) SkipAllAdditionals() error { |
| 597 | for { |
| 598 | if err := p.SkipAdditional(); err == ErrSectionDone { |
| 599 | return nil |
| 600 | } else if err != nil { |
| 601 | return err |
| 602 | } |
| 603 | } |
| 604 | } |
| 605 | |
| 606 | // CNAMEResource parses a single CNAMEResource. |
| 607 | // |
| 608 | // One of the XXXHeader methods must have been called before calling this |
| 609 | // method. |
| 610 | func (p *Parser) CNAMEResource() (CNAMEResource, error) { |
| 611 | if !p.resHeaderValid || p.resHeader.Type != TypeCNAME { |
| 612 | return CNAMEResource{}, ErrNotStarted |
| 613 | } |
| 614 | r, err := unpackCNAMEResource(p.msg, p.off) |
| 615 | if err != nil { |
| 616 | return CNAMEResource{}, err |
| 617 | } |
| 618 | p.off += int(p.resHeader.Length) |
| 619 | p.resHeaderValid = false |
| 620 | p.index++ |
| 621 | return r, nil |
| 622 | } |
| 623 | |
| 624 | // MXResource parses a single MXResource. |
| 625 | // |
| 626 | // One of the XXXHeader methods must have been called before calling this |
| 627 | // method. |
| 628 | func (p *Parser) MXResource() (MXResource, error) { |
| 629 | if !p.resHeaderValid || p.resHeader.Type != TypeMX { |
| 630 | return MXResource{}, ErrNotStarted |
| 631 | } |
| 632 | r, err := unpackMXResource(p.msg, p.off) |
| 633 | if err != nil { |
| 634 | return MXResource{}, err |
| 635 | } |
| 636 | p.off += int(p.resHeader.Length) |
| 637 | p.resHeaderValid = false |
| 638 | p.index++ |
| 639 | return r, nil |
| 640 | } |
| 641 | |
| 642 | // NSResource parses a single NSResource. |
| 643 | // |
| 644 | // One of the XXXHeader methods must have been called before calling this |
| 645 | // method. |
| 646 | func (p *Parser) NSResource() (NSResource, error) { |
| 647 | if !p.resHeaderValid || p.resHeader.Type != TypeNS { |
| 648 | return NSResource{}, ErrNotStarted |
| 649 | } |
| 650 | r, err := unpackNSResource(p.msg, p.off) |
| 651 | if err != nil { |
| 652 | return NSResource{}, err |
| 653 | } |
| 654 | p.off += int(p.resHeader.Length) |
| 655 | p.resHeaderValid = false |
| 656 | p.index++ |
| 657 | return r, nil |
| 658 | } |
| 659 | |
| 660 | // PTRResource parses a single PTRResource. |
| 661 | // |
| 662 | // One of the XXXHeader methods must have been called before calling this |
| 663 | // method. |
| 664 | func (p *Parser) PTRResource() (PTRResource, error) { |
| 665 | if !p.resHeaderValid || p.resHeader.Type != TypePTR { |
| 666 | return PTRResource{}, ErrNotStarted |
| 667 | } |
| 668 | r, err := unpackPTRResource(p.msg, p.off) |
| 669 | if err != nil { |
| 670 | return PTRResource{}, err |
| 671 | } |
| 672 | p.off += int(p.resHeader.Length) |
| 673 | p.resHeaderValid = false |
| 674 | p.index++ |
| 675 | return r, nil |
| 676 | } |
| 677 | |
| 678 | // SOAResource parses a single SOAResource. |
| 679 | // |
| 680 | // One of the XXXHeader methods must have been called before calling this |
| 681 | // method. |
| 682 | func (p *Parser) SOAResource() (SOAResource, error) { |
| 683 | if !p.resHeaderValid || p.resHeader.Type != TypeSOA { |
| 684 | return SOAResource{}, ErrNotStarted |
| 685 | } |
| 686 | r, err := unpackSOAResource(p.msg, p.off) |
| 687 | if err != nil { |
| 688 | return SOAResource{}, err |
| 689 | } |
| 690 | p.off += int(p.resHeader.Length) |
| 691 | p.resHeaderValid = false |
| 692 | p.index++ |
| 693 | return r, nil |
| 694 | } |
| 695 | |
| 696 | // TXTResource parses a single TXTResource. |
| 697 | // |
| 698 | // One of the XXXHeader methods must have been called before calling this |
| 699 | // method. |
| 700 | func (p *Parser) TXTResource() (TXTResource, error) { |
| 701 | if !p.resHeaderValid || p.resHeader.Type != TypeTXT { |
| 702 | return TXTResource{}, ErrNotStarted |
| 703 | } |
| 704 | r, err := unpackTXTResource(p.msg, p.off, p.resHeader.Length) |
| 705 | if err != nil { |
| 706 | return TXTResource{}, err |
| 707 | } |
| 708 | p.off += int(p.resHeader.Length) |
| 709 | p.resHeaderValid = false |
| 710 | p.index++ |
| 711 | return r, nil |
| 712 | } |
| 713 | |
| 714 | // SRVResource parses a single SRVResource. |
| 715 | // |
| 716 | // One of the XXXHeader methods must have been called before calling this |
| 717 | // method. |
| 718 | func (p *Parser) SRVResource() (SRVResource, error) { |
| 719 | if !p.resHeaderValid || p.resHeader.Type != TypeSRV { |
| 720 | return SRVResource{}, ErrNotStarted |
| 721 | } |
| 722 | r, err := unpackSRVResource(p.msg, p.off) |
| 723 | if err != nil { |
| 724 | return SRVResource{}, err |
| 725 | } |
| 726 | p.off += int(p.resHeader.Length) |
| 727 | p.resHeaderValid = false |
| 728 | p.index++ |
| 729 | return r, nil |
| 730 | } |
| 731 | |
| 732 | // AResource parses a single AResource. |
| 733 | // |
| 734 | // One of the XXXHeader methods must have been called before calling this |
| 735 | // method. |
| 736 | func (p *Parser) AResource() (AResource, error) { |
| 737 | if !p.resHeaderValid || p.resHeader.Type != TypeA { |
| 738 | return AResource{}, ErrNotStarted |
| 739 | } |
| 740 | r, err := unpackAResource(p.msg, p.off) |
| 741 | if err != nil { |
| 742 | return AResource{}, err |
| 743 | } |
| 744 | p.off += int(p.resHeader.Length) |
| 745 | p.resHeaderValid = false |
| 746 | p.index++ |
| 747 | return r, nil |
| 748 | } |
| 749 | |
| 750 | // AAAAResource parses a single AAAAResource. |
| 751 | // |
| 752 | // One of the XXXHeader methods must have been called before calling this |
| 753 | // method. |
| 754 | func (p *Parser) AAAAResource() (AAAAResource, error) { |
| 755 | if !p.resHeaderValid || p.resHeader.Type != TypeAAAA { |
| 756 | return AAAAResource{}, ErrNotStarted |
| 757 | } |
| 758 | r, err := unpackAAAAResource(p.msg, p.off) |
| 759 | if err != nil { |
| 760 | return AAAAResource{}, err |
| 761 | } |
| 762 | p.off += int(p.resHeader.Length) |
| 763 | p.resHeaderValid = false |
| 764 | p.index++ |
| 765 | return r, nil |
| 766 | } |
| 767 | |
| 768 | // Unpack parses a full Message. |
| 769 | func (m *Message) Unpack(msg []byte) error { |
| 770 | var p Parser |
| 771 | var err error |
| 772 | if m.Header, err = p.Start(msg); err != nil { |
| 773 | return err |
| 774 | } |
| 775 | if m.Questions, err = p.AllQuestions(); err != nil { |
| 776 | return err |
| 777 | } |
| 778 | if m.Answers, err = p.AllAnswers(); err != nil { |
| 779 | return err |
| 780 | } |
| 781 | if m.Authorities, err = p.AllAuthorities(); err != nil { |
| 782 | return err |
| 783 | } |
| 784 | if m.Additionals, err = p.AllAdditionals(); err != nil { |
| 785 | return err |
| 786 | } |
| 787 | return nil |
| 788 | } |
| 789 | |
| 790 | // Pack packs a full Message. |
| 791 | func (m *Message) Pack() ([]byte, error) { |
| 792 | // Validate the lengths. It is very unlikely that anyone will try to |
| 793 | // pack more than 65535 of any particular type, but it is possible and |
| 794 | // we should fail gracefully. |
| 795 | if len(m.Questions) > int(^uint16(0)) { |
| 796 | return nil, errTooManyQuestions |
| 797 | } |
| 798 | if len(m.Answers) > int(^uint16(0)) { |
| 799 | return nil, errTooManyAnswers |
| 800 | } |
| 801 | if len(m.Authorities) > int(^uint16(0)) { |
| 802 | return nil, errTooManyAuthorities |
| 803 | } |
| 804 | if len(m.Additionals) > int(^uint16(0)) { |
| 805 | return nil, errTooManyAdditionals |
| 806 | } |
| 807 | |
| 808 | var h header |
| 809 | h.id, h.bits = m.Header.pack() |
| 810 | |
| 811 | h.questions = uint16(len(m.Questions)) |
| 812 | h.answers = uint16(len(m.Answers)) |
| 813 | h.authorities = uint16(len(m.Authorities)) |
| 814 | h.additionals = uint16(len(m.Additionals)) |
| 815 | |
| 816 | msg := make([]byte, 0, packStartingCap) |
| 817 | |
| 818 | msg = h.pack(msg) |
| 819 | |
| 820 | // RFC 1035 allows (but does not require) compression for packing. RFC |
| 821 | // 1035 requires unpacking implementations to support compression, so |
| 822 | // unconditionally enabling it is fine. |
| 823 | // |
| 824 | // DNS lookups are typically done over UDP, and RFC 1035 states that UDP |
| 825 | // DNS packets can be a maximum of 512 bytes long. Without compression, |
| 826 | // many DNS response packets are over this limit, so enabling |
| 827 | // compression will help ensure compliance. |
| 828 | compression := map[string]int{} |
| 829 | |
| 830 | for i := range m.Questions { |
| 831 | var err error |
| 832 | if msg, err = m.Questions[i].pack(msg, compression); err != nil { |
| 833 | return nil, &nestedError{"packing Question", err} |
| 834 | } |
| 835 | } |
| 836 | for i := range m.Answers { |
| 837 | var err error |
| 838 | if msg, err = m.Answers[i].pack(msg, compression); err != nil { |
| 839 | return nil, &nestedError{"packing Answer", err} |
| 840 | } |
| 841 | } |
| 842 | for i := range m.Authorities { |
| 843 | var err error |
| 844 | if msg, err = m.Authorities[i].pack(msg, compression); err != nil { |
| 845 | return nil, &nestedError{"packing Authority", err} |
| 846 | } |
| 847 | } |
| 848 | for i := range m.Additionals { |
| 849 | var err error |
| 850 | if msg, err = m.Additionals[i].pack(msg, compression); err != nil { |
| 851 | return nil, &nestedError{"packing Additional", err} |
| 852 | } |
| 853 | } |
| 854 | |
| 855 | return msg, nil |
| 856 | } |
| 857 | |
| 858 | // A Builder allows incrementally packing a DNS message. |
| 859 | type Builder struct { |
| 860 | msg []byte |
| 861 | header header |
| 862 | section section |
| 863 | compression map[string]int |
| 864 | } |
| 865 | |
| 866 | // Start initializes the builder. |
| 867 | // |
| 868 | // buf is optional (nil is fine), but if provided, Start takes ownership of buf. |
| 869 | func (b *Builder) Start(buf []byte, h Header) { |
| 870 | b.StartWithoutCompression(buf, h) |
| 871 | b.compression = map[string]int{} |
| 872 | } |
| 873 | |
| 874 | // StartWithoutCompression initializes the builder with compression disabled. |
| 875 | // |
| 876 | // This avoids compression related allocations, but can result in larger message |
| 877 | // sizes. Be careful with this mode as it can cause messages to exceed the UDP |
| 878 | // size limit. |
| 879 | // |
| 880 | // buf is optional (nil is fine), but if provided, Start takes ownership of buf. |
| 881 | func (b *Builder) StartWithoutCompression(buf []byte, h Header) { |
| 882 | *b = Builder{msg: buf} |
| 883 | b.header.id, b.header.bits = h.pack() |
| 884 | if cap(b.msg) < headerLen { |
| 885 | b.msg = make([]byte, 0, packStartingCap) |
| 886 | } |
| 887 | b.msg = b.msg[:headerLen] |
| 888 | b.section = sectionHeader |
| 889 | } |
| 890 | |
| 891 | func (b *Builder) startCheck(s section) error { |
| 892 | if b.section <= sectionNotStarted { |
| 893 | return ErrNotStarted |
| 894 | } |
| 895 | if b.section > s { |
| 896 | return ErrSectionDone |
| 897 | } |
| 898 | return nil |
| 899 | } |
| 900 | |
| 901 | // StartQuestions prepares the builder for packing Questions. |
| 902 | func (b *Builder) StartQuestions() error { |
| 903 | if err := b.startCheck(sectionQuestions); err != nil { |
| 904 | return err |
| 905 | } |
| 906 | b.section = sectionQuestions |
| 907 | return nil |
| 908 | } |
| 909 | |
| 910 | // StartAnswers prepares the builder for packing Answers. |
| 911 | func (b *Builder) StartAnswers() error { |
| 912 | if err := b.startCheck(sectionAnswers); err != nil { |
| 913 | return err |
| 914 | } |
| 915 | b.section = sectionAnswers |
| 916 | return nil |
| 917 | } |
| 918 | |
| 919 | // StartAuthorities prepares the builder for packing Authorities. |
| 920 | func (b *Builder) StartAuthorities() error { |
| 921 | if err := b.startCheck(sectionAuthorities); err != nil { |
| 922 | return err |
| 923 | } |
| 924 | b.section = sectionAuthorities |
| 925 | return nil |
| 926 | } |
| 927 | |
| 928 | // StartAdditionals prepares the builder for packing Additionals. |
| 929 | func (b *Builder) StartAdditionals() error { |
| 930 | if err := b.startCheck(sectionAdditionals); err != nil { |
| 931 | return err |
| 932 | } |
| 933 | b.section = sectionAdditionals |
| 934 | return nil |
| 935 | } |
| 936 | |
| 937 | func (b *Builder) incrementSectionCount() error { |
| 938 | var count *uint16 |
| 939 | var err error |
| 940 | switch b.section { |
| 941 | case sectionQuestions: |
| 942 | count = &b.header.questions |
| 943 | err = errTooManyQuestions |
| 944 | case sectionAnswers: |
| 945 | count = &b.header.answers |
| 946 | err = errTooManyAnswers |
| 947 | case sectionAuthorities: |
| 948 | count = &b.header.authorities |
| 949 | err = errTooManyAuthorities |
| 950 | case sectionAdditionals: |
| 951 | count = &b.header.additionals |
| 952 | err = errTooManyAdditionals |
| 953 | } |
| 954 | if *count == ^uint16(0) { |
| 955 | return err |
| 956 | } |
| 957 | *count++ |
| 958 | return nil |
| 959 | } |
| 960 | |
| 961 | // Question adds a single Question. |
| 962 | func (b *Builder) Question(q Question) error { |
| 963 | if b.section < sectionQuestions { |
| 964 | return ErrNotStarted |
| 965 | } |
| 966 | if b.section > sectionQuestions { |
| 967 | return ErrSectionDone |
| 968 | } |
| 969 | msg, err := q.pack(b.msg, b.compression) |
| 970 | if err != nil { |
| 971 | return err |
| 972 | } |
| 973 | if err := b.incrementSectionCount(); err != nil { |
| 974 | return err |
| 975 | } |
| 976 | b.msg = msg |
| 977 | return nil |
| 978 | } |
| 979 | |
| 980 | func (b *Builder) checkResourceSection() error { |
| 981 | if b.section < sectionAnswers { |
| 982 | return ErrNotStarted |
| 983 | } |
| 984 | if b.section > sectionAdditionals { |
| 985 | return ErrSectionDone |
| 986 | } |
| 987 | return nil |
| 988 | } |
| 989 | |
| 990 | // CNAMEResource adds a single CNAMEResource. |
| 991 | func (b *Builder) CNAMEResource(h ResourceHeader, r CNAMEResource) error { |
| 992 | if err := b.checkResourceSection(); err != nil { |
| 993 | return err |
| 994 | } |
| 995 | h.Type = r.realType() |
| 996 | msg, length, err := h.pack(b.msg, b.compression) |
| 997 | if err != nil { |
| 998 | return &nestedError{"ResourceHeader", err} |
| 999 | } |
| 1000 | preLen := len(msg) |
| 1001 | if msg, err = r.pack(msg, b.compression); err != nil { |
| 1002 | return &nestedError{"CNAMEResource body", err} |
| 1003 | } |
| 1004 | if err := h.fixLen(msg, length, preLen); err != nil { |
| 1005 | return err |
| 1006 | } |
| 1007 | if err := b.incrementSectionCount(); err != nil { |
| 1008 | return err |
| 1009 | } |
| 1010 | b.msg = msg |
| 1011 | return nil |
| 1012 | } |
| 1013 | |
| 1014 | // MXResource adds a single MXResource. |
| 1015 | func (b *Builder) MXResource(h ResourceHeader, r MXResource) error { |
| 1016 | if err := b.checkResourceSection(); err != nil { |
| 1017 | return err |
| 1018 | } |
| 1019 | h.Type = r.realType() |
| 1020 | msg, length, err := h.pack(b.msg, b.compression) |
| 1021 | if err != nil { |
| 1022 | return &nestedError{"ResourceHeader", err} |
| 1023 | } |
| 1024 | preLen := len(msg) |
| 1025 | if msg, err = r.pack(msg, b.compression); err != nil { |
| 1026 | return &nestedError{"MXResource body", err} |
| 1027 | } |
| 1028 | if err := h.fixLen(msg, length, preLen); err != nil { |
| 1029 | return err |
| 1030 | } |
| 1031 | if err := b.incrementSectionCount(); err != nil { |
| 1032 | return err |
| 1033 | } |
| 1034 | b.msg = msg |
| 1035 | return nil |
| 1036 | } |
| 1037 | |
| 1038 | // NSResource adds a single NSResource. |
| 1039 | func (b *Builder) NSResource(h ResourceHeader, r NSResource) error { |
| 1040 | if err := b.checkResourceSection(); err != nil { |
| 1041 | return err |
| 1042 | } |
| 1043 | h.Type = r.realType() |
| 1044 | msg, length, err := h.pack(b.msg, b.compression) |
| 1045 | if err != nil { |
| 1046 | return &nestedError{"ResourceHeader", err} |
| 1047 | } |
| 1048 | preLen := len(msg) |
| 1049 | if msg, err = r.pack(msg, b.compression); err != nil { |
| 1050 | return &nestedError{"NSResource body", err} |
| 1051 | } |
| 1052 | if err := h.fixLen(msg, length, preLen); err != nil { |
| 1053 | return err |
| 1054 | } |
| 1055 | if err := b.incrementSectionCount(); err != nil { |
| 1056 | return err |
| 1057 | } |
| 1058 | b.msg = msg |
| 1059 | return nil |
| 1060 | } |
| 1061 | |
| 1062 | // PTRResource adds a single PTRResource. |
| 1063 | func (b *Builder) PTRResource(h ResourceHeader, r PTRResource) error { |
| 1064 | if err := b.checkResourceSection(); err != nil { |
| 1065 | return err |
| 1066 | } |
| 1067 | h.Type = r.realType() |
| 1068 | msg, length, err := h.pack(b.msg, b.compression) |
| 1069 | if err != nil { |
| 1070 | return &nestedError{"ResourceHeader", err} |
| 1071 | } |
| 1072 | preLen := len(msg) |
| 1073 | if msg, err = r.pack(msg, b.compression); err != nil { |
| 1074 | return &nestedError{"PTRResource body", err} |
| 1075 | } |
| 1076 | if err := h.fixLen(msg, length, preLen); err != nil { |
| 1077 | return err |
| 1078 | } |
| 1079 | if err := b.incrementSectionCount(); err != nil { |
| 1080 | return err |
| 1081 | } |
| 1082 | b.msg = msg |
| 1083 | return nil |
| 1084 | } |
| 1085 | |
| 1086 | // SOAResource adds a single SOAResource. |
| 1087 | func (b *Builder) SOAResource(h ResourceHeader, r SOAResource) error { |
| 1088 | if err := b.checkResourceSection(); err != nil { |
| 1089 | return err |
| 1090 | } |
| 1091 | h.Type = r.realType() |
| 1092 | msg, length, err := h.pack(b.msg, b.compression) |
| 1093 | if err != nil { |
| 1094 | return &nestedError{"ResourceHeader", err} |
| 1095 | } |
| 1096 | preLen := len(msg) |
| 1097 | if msg, err = r.pack(msg, b.compression); err != nil { |
| 1098 | return &nestedError{"SOAResource body", err} |
| 1099 | } |
| 1100 | if err := h.fixLen(msg, length, preLen); err != nil { |
| 1101 | return err |
| 1102 | } |
| 1103 | if err := b.incrementSectionCount(); err != nil { |
| 1104 | return err |
| 1105 | } |
| 1106 | b.msg = msg |
| 1107 | return nil |
| 1108 | } |
| 1109 | |
| 1110 | // TXTResource adds a single TXTResource. |
| 1111 | func (b *Builder) TXTResource(h ResourceHeader, r TXTResource) error { |
| 1112 | if err := b.checkResourceSection(); err != nil { |
| 1113 | return err |
| 1114 | } |
| 1115 | h.Type = r.realType() |
| 1116 | msg, length, err := h.pack(b.msg, b.compression) |
| 1117 | if err != nil { |
| 1118 | return &nestedError{"ResourceHeader", err} |
| 1119 | } |
| 1120 | preLen := len(msg) |
| 1121 | if msg, err = r.pack(msg, b.compression); err != nil { |
| 1122 | return &nestedError{"TXTResource body", err} |
| 1123 | } |
| 1124 | if err := h.fixLen(msg, length, preLen); err != nil { |
| 1125 | return err |
| 1126 | } |
| 1127 | if err := b.incrementSectionCount(); err != nil { |
| 1128 | return err |
| 1129 | } |
| 1130 | b.msg = msg |
| 1131 | return nil |
| 1132 | } |
| 1133 | |
| 1134 | // SRVResource adds a single SRVResource. |
| 1135 | func (b *Builder) SRVResource(h ResourceHeader, r SRVResource) error { |
| 1136 | if err := b.checkResourceSection(); err != nil { |
| 1137 | return err |
| 1138 | } |
| 1139 | h.Type = r.realType() |
| 1140 | msg, length, err := h.pack(b.msg, b.compression) |
| 1141 | if err != nil { |
| 1142 | return &nestedError{"ResourceHeader", err} |
| 1143 | } |
| 1144 | preLen := len(msg) |
| 1145 | if msg, err = r.pack(msg, b.compression); err != nil { |
| 1146 | return &nestedError{"SRVResource body", err} |
| 1147 | } |
| 1148 | if err := h.fixLen(msg, length, preLen); err != nil { |
| 1149 | return err |
| 1150 | } |
| 1151 | if err := b.incrementSectionCount(); err != nil { |
| 1152 | return err |
| 1153 | } |
| 1154 | b.msg = msg |
| 1155 | return nil |
| 1156 | } |
| 1157 | |
| 1158 | // AResource adds a single AResource. |
| 1159 | func (b *Builder) AResource(h ResourceHeader, r AResource) error { |
| 1160 | if err := b.checkResourceSection(); err != nil { |
| 1161 | return err |
| 1162 | } |
| 1163 | h.Type = r.realType() |
| 1164 | msg, length, err := h.pack(b.msg, b.compression) |
| 1165 | if err != nil { |
| 1166 | return &nestedError{"ResourceHeader", err} |
| 1167 | } |
| 1168 | preLen := len(msg) |
| 1169 | if msg, err = r.pack(msg, b.compression); err != nil { |
| 1170 | return &nestedError{"AResource body", err} |
| 1171 | } |
| 1172 | if err := h.fixLen(msg, length, preLen); err != nil { |
| 1173 | return err |
| 1174 | } |
| 1175 | if err := b.incrementSectionCount(); err != nil { |
| 1176 | return err |
| 1177 | } |
| 1178 | b.msg = msg |
| 1179 | return nil |
| 1180 | } |
| 1181 | |
| 1182 | // AAAAResource adds a single AAAAResource. |
| 1183 | func (b *Builder) AAAAResource(h ResourceHeader, r AAAAResource) error { |
| 1184 | if err := b.checkResourceSection(); err != nil { |
| 1185 | return err |
| 1186 | } |
| 1187 | h.Type = r.realType() |
| 1188 | msg, length, err := h.pack(b.msg, b.compression) |
| 1189 | if err != nil { |
| 1190 | return &nestedError{"ResourceHeader", err} |
| 1191 | } |
| 1192 | preLen := len(msg) |
| 1193 | if msg, err = r.pack(msg, b.compression); err != nil { |
| 1194 | return &nestedError{"AAAAResource body", err} |
| 1195 | } |
| 1196 | if err := h.fixLen(msg, length, preLen); err != nil { |
| 1197 | return err |
| 1198 | } |
| 1199 | if err := b.incrementSectionCount(); err != nil { |
| 1200 | return err |
| 1201 | } |
| 1202 | b.msg = msg |
| 1203 | return nil |
| 1204 | } |
| 1205 | |
| 1206 | // Finish ends message building and generates a binary packet. |
| 1207 | func (b *Builder) Finish() ([]byte, error) { |
| 1208 | if b.section < sectionHeader { |
| 1209 | return nil, ErrNotStarted |
| 1210 | } |
| 1211 | b.section = sectionDone |
| 1212 | b.header.pack(b.msg[:0]) |
| 1213 | return b.msg, nil |
| 1214 | } |
| 1215 | |
| 1216 | // A ResourceHeader is the header of a DNS resource record. There are |
| 1217 | // many types of DNS resource records, but they all share the same header. |
| 1218 | type ResourceHeader struct { |
| 1219 | // Name is the domain name for which this resource record pertains. |
| 1220 | Name Name |
| 1221 | |
| 1222 | // Type is the type of DNS resource record. |
| 1223 | // |
| 1224 | // This field will be set automatically during packing. |
| 1225 | Type Type |
| 1226 | |
| 1227 | // Class is the class of network to which this DNS resource record |
| 1228 | // pertains. |
| 1229 | Class Class |
| 1230 | |
| 1231 | // TTL is the length of time (measured in seconds) which this resource |
| 1232 | // record is valid for (time to live). All Resources in a set should |
| 1233 | // have the same TTL (RFC 2181 Section 5.2). |
| 1234 | TTL uint32 |
| 1235 | |
| 1236 | // Length is the length of data in the resource record after the header. |
| 1237 | // |
| 1238 | // This field will be set automatically during packing. |
| 1239 | Length uint16 |
| 1240 | } |
| 1241 | |
| 1242 | // pack packs all of the fields in a ResourceHeader except for the length. The |
| 1243 | // length bytes are returned as a slice so they can be filled in after the rest |
| 1244 | // of the Resource has been packed. |
| 1245 | func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int) (msg []byte, length []byte, err error) { |
| 1246 | msg = oldMsg |
| 1247 | if msg, err = h.Name.pack(msg, compression); err != nil { |
| 1248 | return oldMsg, nil, &nestedError{"Name", err} |
| 1249 | } |
| 1250 | msg = packType(msg, h.Type) |
| 1251 | msg = packClass(msg, h.Class) |
| 1252 | msg = packUint32(msg, h.TTL) |
| 1253 | lenBegin := len(msg) |
| 1254 | msg = packUint16(msg, h.Length) |
| 1255 | return msg, msg[lenBegin : lenBegin+uint16Len], nil |
| 1256 | } |
| 1257 | |
| 1258 | func (h *ResourceHeader) unpack(msg []byte, off int) (int, error) { |
| 1259 | newOff := off |
| 1260 | var err error |
| 1261 | if newOff, err = h.Name.unpack(msg, newOff); err != nil { |
| 1262 | return off, &nestedError{"Name", err} |
| 1263 | } |
| 1264 | if h.Type, newOff, err = unpackType(msg, newOff); err != nil { |
| 1265 | return off, &nestedError{"Type", err} |
| 1266 | } |
| 1267 | if h.Class, newOff, err = unpackClass(msg, newOff); err != nil { |
| 1268 | return off, &nestedError{"Class", err} |
| 1269 | } |
| 1270 | if h.TTL, newOff, err = unpackUint32(msg, newOff); err != nil { |
| 1271 | return off, &nestedError{"TTL", err} |
| 1272 | } |
| 1273 | if h.Length, newOff, err = unpackUint16(msg, newOff); err != nil { |
| 1274 | return off, &nestedError{"Length", err} |
| 1275 | } |
| 1276 | return newOff, nil |
| 1277 | } |
| 1278 | |
| 1279 | func (h *ResourceHeader) fixLen(msg []byte, length []byte, preLen int) error { |
| 1280 | conLen := len(msg) - preLen |
| 1281 | if conLen > int(^uint16(0)) { |
| 1282 | return errResTooLong |
| 1283 | } |
| 1284 | |
| 1285 | // Fill in the length now that we know how long the content is. |
| 1286 | packUint16(length[:0], uint16(conLen)) |
| 1287 | h.Length = uint16(conLen) |
| 1288 | |
| 1289 | return nil |
| 1290 | } |
| 1291 | |
| 1292 | func skipResource(msg []byte, off int) (int, error) { |
| 1293 | newOff, err := skipName(msg, off) |
| 1294 | if err != nil { |
| 1295 | return off, &nestedError{"Name", err} |
| 1296 | } |
| 1297 | if newOff, err = skipType(msg, newOff); err != nil { |
| 1298 | return off, &nestedError{"Type", err} |
| 1299 | } |
| 1300 | if newOff, err = skipClass(msg, newOff); err != nil { |
| 1301 | return off, &nestedError{"Class", err} |
| 1302 | } |
| 1303 | if newOff, err = skipUint32(msg, newOff); err != nil { |
| 1304 | return off, &nestedError{"TTL", err} |
| 1305 | } |
| 1306 | length, newOff, err := unpackUint16(msg, newOff) |
| 1307 | if err != nil { |
| 1308 | return off, &nestedError{"Length", err} |
| 1309 | } |
| 1310 | if newOff += int(length); newOff > len(msg) { |
| 1311 | return off, errResourceLen |
| 1312 | } |
| 1313 | return newOff, nil |
| 1314 | } |
| 1315 | |
| 1316 | func packUint16(msg []byte, field uint16) []byte { |
| 1317 | return append(msg, byte(field>>8), byte(field)) |
| 1318 | } |
| 1319 | |
| 1320 | func unpackUint16(msg []byte, off int) (uint16, int, error) { |
| 1321 | if off+uint16Len > len(msg) { |
| 1322 | return 0, off, errBaseLen |
| 1323 | } |
| 1324 | return uint16(msg[off])<<8 | uint16(msg[off+1]), off + uint16Len, nil |
| 1325 | } |
| 1326 | |
| 1327 | func skipUint16(msg []byte, off int) (int, error) { |
| 1328 | if off+uint16Len > len(msg) { |
| 1329 | return off, errBaseLen |
| 1330 | } |
| 1331 | return off + uint16Len, nil |
| 1332 | } |
| 1333 | |
| 1334 | func packType(msg []byte, field Type) []byte { |
| 1335 | return packUint16(msg, uint16(field)) |
| 1336 | } |
| 1337 | |
| 1338 | func unpackType(msg []byte, off int) (Type, int, error) { |
| 1339 | t, o, err := unpackUint16(msg, off) |
| 1340 | return Type(t), o, err |
| 1341 | } |
| 1342 | |
| 1343 | func skipType(msg []byte, off int) (int, error) { |
| 1344 | return skipUint16(msg, off) |
| 1345 | } |
| 1346 | |
| 1347 | func packClass(msg []byte, field Class) []byte { |
| 1348 | return packUint16(msg, uint16(field)) |
| 1349 | } |
| 1350 | |
| 1351 | func unpackClass(msg []byte, off int) (Class, int, error) { |
| 1352 | c, o, err := unpackUint16(msg, off) |
| 1353 | return Class(c), o, err |
| 1354 | } |
| 1355 | |
| 1356 | func skipClass(msg []byte, off int) (int, error) { |
| 1357 | return skipUint16(msg, off) |
| 1358 | } |
| 1359 | |
| 1360 | func packUint32(msg []byte, field uint32) []byte { |
| 1361 | return append( |
| 1362 | msg, |
| 1363 | byte(field>>24), |
| 1364 | byte(field>>16), |
| 1365 | byte(field>>8), |
| 1366 | byte(field), |
| 1367 | ) |
| 1368 | } |
| 1369 | |
| 1370 | func unpackUint32(msg []byte, off int) (uint32, int, error) { |
| 1371 | if off+uint32Len > len(msg) { |
| 1372 | return 0, off, errBaseLen |
| 1373 | } |
| 1374 | v := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3]) |
| 1375 | return v, off + uint32Len, nil |
| 1376 | } |
| 1377 | |
| 1378 | func skipUint32(msg []byte, off int) (int, error) { |
| 1379 | if off+uint32Len > len(msg) { |
| 1380 | return off, errBaseLen |
| 1381 | } |
| 1382 | return off + uint32Len, nil |
| 1383 | } |
| 1384 | |
| 1385 | func packText(msg []byte, field string) []byte { |
| 1386 | for len(field) > 0 { |
| 1387 | l := len(field) |
| 1388 | if l > 255 { |
| 1389 | l = 255 |
| 1390 | } |
| 1391 | msg = append(msg, byte(l)) |
| 1392 | msg = append(msg, field[:l]...) |
| 1393 | field = field[l:] |
| 1394 | } |
| 1395 | return msg |
| 1396 | } |
| 1397 | |
| 1398 | func unpackText(msg []byte, off int) (string, int, error) { |
| 1399 | if off >= len(msg) { |
| 1400 | return "", off, errBaseLen |
| 1401 | } |
| 1402 | beginOff := off + 1 |
| 1403 | endOff := beginOff + int(msg[off]) |
| 1404 | if endOff > len(msg) { |
| 1405 | return "", off, errCalcLen |
| 1406 | } |
| 1407 | return string(msg[beginOff:endOff]), endOff, nil |
| 1408 | } |
| 1409 | |
| 1410 | func skipText(msg []byte, off int) (int, error) { |
| 1411 | if off >= len(msg) { |
| 1412 | return off, errBaseLen |
| 1413 | } |
| 1414 | endOff := off + 1 + int(msg[off]) |
| 1415 | if endOff > len(msg) { |
| 1416 | return off, errCalcLen |
| 1417 | } |
| 1418 | return endOff, nil |
| 1419 | } |
| 1420 | |
| 1421 | func packBytes(msg []byte, field []byte) []byte { |
| 1422 | return append(msg, field...) |
| 1423 | } |
| 1424 | |
| 1425 | func unpackBytes(msg []byte, off int, field []byte) (int, error) { |
| 1426 | newOff := off + len(field) |
| 1427 | if newOff > len(msg) { |
| 1428 | return off, errBaseLen |
| 1429 | } |
| 1430 | copy(field, msg[off:newOff]) |
| 1431 | return newOff, nil |
| 1432 | } |
| 1433 | |
| 1434 | func skipBytes(msg []byte, off int, field []byte) (int, error) { |
| 1435 | newOff := off + len(field) |
| 1436 | if newOff > len(msg) { |
| 1437 | return off, errBaseLen |
| 1438 | } |
| 1439 | return newOff, nil |
| 1440 | } |
| 1441 | |
| 1442 | const nameLen = 255 |
| 1443 | |
| 1444 | // A Name is a non-encoded domain name. It is used instead of strings to avoid |
| 1445 | // allocations. |
| 1446 | type Name struct { |
| 1447 | Data [nameLen]byte |
| 1448 | Length uint8 |
| 1449 | } |
| 1450 | |
| 1451 | // NewName creates a new Name from a string. |
| 1452 | func NewName(name string) (Name, error) { |
| 1453 | if len([]byte(name)) > nameLen { |
| 1454 | return Name{}, errCalcLen |
| 1455 | } |
| 1456 | n := Name{Length: uint8(len(name))} |
| 1457 | copy(n.Data[:], []byte(name)) |
| 1458 | return n, nil |
| 1459 | } |
| 1460 | |
| 1461 | func (n Name) String() string { |
| 1462 | return string(n.Data[:n.Length]) |
| 1463 | } |
| 1464 | |
| 1465 | // pack packs a domain name. |
| 1466 | // |
| 1467 | // Domain names are a sequence of counted strings split at the dots. They end |
| 1468 | // with a zero-length string. Compression can be used to reuse domain suffixes. |
| 1469 | // |
| 1470 | // The compression map will be updated with new domain suffixes. If compression |
| 1471 | // is nil, compression will not be used. |
| 1472 | func (n *Name) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1473 | oldMsg := msg |
| 1474 | |
| 1475 | // Add a trailing dot to canonicalize name. |
| 1476 | if n.Length == 0 || n.Data[n.Length-1] != '.' { |
| 1477 | return oldMsg, errNonCanonicalName |
| 1478 | } |
| 1479 | |
| 1480 | // Allow root domain. |
| 1481 | if n.Data[0] == '.' && n.Length == 1 { |
| 1482 | return append(msg, 0), nil |
| 1483 | } |
| 1484 | |
| 1485 | // Emit sequence of counted strings, chopping at dots. |
| 1486 | for i, begin := 0, 0; i < int(n.Length); i++ { |
| 1487 | // Check for the end of the segment. |
| 1488 | if n.Data[i] == '.' { |
| 1489 | // The two most significant bits have special meaning. |
| 1490 | // It isn't allowed for segments to be long enough to |
| 1491 | // need them. |
| 1492 | if i-begin >= 1<<6 { |
| 1493 | return oldMsg, errSegTooLong |
| 1494 | } |
| 1495 | |
| 1496 | // Segments must have a non-zero length. |
| 1497 | if i-begin == 0 { |
| 1498 | return oldMsg, errZeroSegLen |
| 1499 | } |
| 1500 | |
| 1501 | msg = append(msg, byte(i-begin)) |
| 1502 | |
| 1503 | for j := begin; j < i; j++ { |
| 1504 | msg = append(msg, n.Data[j]) |
| 1505 | } |
| 1506 | |
| 1507 | begin = i + 1 |
| 1508 | continue |
| 1509 | } |
| 1510 | |
| 1511 | // We can only compress domain suffixes starting with a new |
| 1512 | // segment. A pointer is two bytes with the two most significant |
| 1513 | // bits set to 1 to indicate that it is a pointer. |
| 1514 | if (i == 0 || n.Data[i-1] == '.') && compression != nil { |
| 1515 | if ptr, ok := compression[string(n.Data[i:])]; ok { |
| 1516 | // Hit. Emit a pointer instead of the rest of |
| 1517 | // the domain. |
| 1518 | return append(msg, byte(ptr>>8|0xC0), byte(ptr)), nil |
| 1519 | } |
| 1520 | |
| 1521 | // Miss. Add the suffix to the compression table if the |
| 1522 | // offset can be stored in the available 14 bytes. |
| 1523 | if len(msg) <= int(^uint16(0)>>2) { |
| 1524 | compression[string(n.Data[i:])] = len(msg) |
| 1525 | } |
| 1526 | } |
| 1527 | } |
| 1528 | return append(msg, 0), nil |
| 1529 | } |
| 1530 | |
| 1531 | // unpack unpacks a domain name. |
| 1532 | func (n *Name) unpack(msg []byte, off int) (int, error) { |
| 1533 | // currOff is the current working offset. |
| 1534 | currOff := off |
| 1535 | |
| 1536 | // newOff is the offset where the next record will start. Pointers lead |
| 1537 | // to data that belongs to other names and thus doesn't count towards to |
| 1538 | // the usage of this name. |
| 1539 | newOff := off |
| 1540 | |
| 1541 | // ptr is the number of pointers followed. |
| 1542 | var ptr int |
| 1543 | |
| 1544 | // Name is a slice representation of the name data. |
| 1545 | name := n.Data[:0] |
| 1546 | |
| 1547 | Loop: |
| 1548 | for { |
| 1549 | if currOff >= len(msg) { |
| 1550 | return off, errBaseLen |
| 1551 | } |
| 1552 | c := int(msg[currOff]) |
| 1553 | currOff++ |
| 1554 | switch c & 0xC0 { |
| 1555 | case 0x00: // String segment |
| 1556 | if c == 0x00 { |
| 1557 | // A zero length signals the end of the name. |
| 1558 | break Loop |
| 1559 | } |
| 1560 | endOff := currOff + c |
| 1561 | if endOff > len(msg) { |
| 1562 | return off, errCalcLen |
| 1563 | } |
| 1564 | name = append(name, msg[currOff:endOff]...) |
| 1565 | name = append(name, '.') |
| 1566 | currOff = endOff |
| 1567 | case 0xC0: // Pointer |
| 1568 | if currOff >= len(msg) { |
| 1569 | return off, errInvalidPtr |
| 1570 | } |
| 1571 | c1 := msg[currOff] |
| 1572 | currOff++ |
| 1573 | if ptr == 0 { |
| 1574 | newOff = currOff |
| 1575 | } |
| 1576 | // Don't follow too many pointers, maybe there's a loop. |
| 1577 | if ptr++; ptr > 10 { |
| 1578 | return off, errTooManyPtr |
| 1579 | } |
| 1580 | currOff = (c^0xC0)<<8 | int(c1) |
| 1581 | default: |
| 1582 | // Prefixes 0x80 and 0x40 are reserved. |
| 1583 | return off, errReserved |
| 1584 | } |
| 1585 | } |
| 1586 | if len(name) == 0 { |
| 1587 | name = append(name, '.') |
| 1588 | } |
| 1589 | if len(name) > len(n.Data) { |
| 1590 | return off, errCalcLen |
| 1591 | } |
| 1592 | n.Length = uint8(len(name)) |
| 1593 | if ptr == 0 { |
| 1594 | newOff = currOff |
| 1595 | } |
| 1596 | return newOff, nil |
| 1597 | } |
| 1598 | |
| 1599 | func skipName(msg []byte, off int) (int, error) { |
| 1600 | // newOff is the offset where the next record will start. Pointers lead |
| 1601 | // to data that belongs to other names and thus doesn't count towards to |
| 1602 | // the usage of this name. |
| 1603 | newOff := off |
| 1604 | |
| 1605 | Loop: |
| 1606 | for { |
| 1607 | if newOff >= len(msg) { |
| 1608 | return off, errBaseLen |
| 1609 | } |
| 1610 | c := int(msg[newOff]) |
| 1611 | newOff++ |
| 1612 | switch c & 0xC0 { |
| 1613 | case 0x00: |
| 1614 | if c == 0x00 { |
| 1615 | // A zero length signals the end of the name. |
| 1616 | break Loop |
| 1617 | } |
| 1618 | // literal string |
| 1619 | newOff += c |
| 1620 | if newOff > len(msg) { |
| 1621 | return off, errCalcLen |
| 1622 | } |
| 1623 | case 0xC0: |
| 1624 | // Pointer to somewhere else in msg. |
| 1625 | |
| 1626 | // Pointers are two bytes. |
| 1627 | newOff++ |
| 1628 | |
| 1629 | // Don't follow the pointer as the data here has ended. |
| 1630 | break Loop |
| 1631 | default: |
| 1632 | // Prefixes 0x80 and 0x40 are reserved. |
| 1633 | return off, errReserved |
| 1634 | } |
| 1635 | } |
| 1636 | |
| 1637 | return newOff, nil |
| 1638 | } |
| 1639 | |
| 1640 | // A Question is a DNS query. |
| 1641 | type Question struct { |
| 1642 | Name Name |
| 1643 | Type Type |
| 1644 | Class Class |
| 1645 | } |
| 1646 | |
| 1647 | func (q *Question) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1648 | msg, err := q.Name.pack(msg, compression) |
| 1649 | if err != nil { |
| 1650 | return msg, &nestedError{"Name", err} |
| 1651 | } |
| 1652 | msg = packType(msg, q.Type) |
| 1653 | return packClass(msg, q.Class), nil |
| 1654 | } |
| 1655 | |
| 1656 | func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, int, error) { |
| 1657 | var ( |
| 1658 | r ResourceBody |
| 1659 | err error |
| 1660 | name string |
| 1661 | ) |
| 1662 | switch hdr.Type { |
| 1663 | case TypeA: |
| 1664 | var rb AResource |
| 1665 | rb, err = unpackAResource(msg, off) |
| 1666 | r = &rb |
| 1667 | name = "A" |
| 1668 | case TypeNS: |
| 1669 | var rb NSResource |
| 1670 | rb, err = unpackNSResource(msg, off) |
| 1671 | r = &rb |
| 1672 | name = "NS" |
| 1673 | case TypeCNAME: |
| 1674 | var rb CNAMEResource |
| 1675 | rb, err = unpackCNAMEResource(msg, off) |
| 1676 | r = &rb |
| 1677 | name = "CNAME" |
| 1678 | case TypeSOA: |
| 1679 | var rb SOAResource |
| 1680 | rb, err = unpackSOAResource(msg, off) |
| 1681 | r = &rb |
| 1682 | name = "SOA" |
| 1683 | case TypePTR: |
| 1684 | var rb PTRResource |
| 1685 | rb, err = unpackPTRResource(msg, off) |
| 1686 | r = &rb |
| 1687 | name = "PTR" |
| 1688 | case TypeMX: |
| 1689 | var rb MXResource |
| 1690 | rb, err = unpackMXResource(msg, off) |
| 1691 | r = &rb |
| 1692 | name = "MX" |
| 1693 | case TypeTXT: |
| 1694 | var rb TXTResource |
| 1695 | rb, err = unpackTXTResource(msg, off, hdr.Length) |
| 1696 | r = &rb |
| 1697 | name = "TXT" |
| 1698 | case TypeAAAA: |
| 1699 | var rb AAAAResource |
| 1700 | rb, err = unpackAAAAResource(msg, off) |
| 1701 | r = &rb |
| 1702 | name = "AAAA" |
| 1703 | case TypeSRV: |
| 1704 | var rb SRVResource |
| 1705 | rb, err = unpackSRVResource(msg, off) |
| 1706 | r = &rb |
| 1707 | name = "SRV" |
| 1708 | } |
| 1709 | if err != nil { |
| 1710 | return nil, off, &nestedError{name + " record", err} |
| 1711 | } |
| 1712 | if r == nil { |
| 1713 | return nil, off, errors.New("invalid resource type: " + string(hdr.Type+'0')) |
| 1714 | } |
| 1715 | return r, off + int(hdr.Length), nil |
| 1716 | } |
| 1717 | |
| 1718 | // A CNAMEResource is a CNAME Resource record. |
| 1719 | type CNAMEResource struct { |
| 1720 | CNAME Name |
| 1721 | } |
| 1722 | |
| 1723 | func (r *CNAMEResource) realType() Type { |
| 1724 | return TypeCNAME |
| 1725 | } |
| 1726 | |
| 1727 | func (r *CNAMEResource) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1728 | return r.CNAME.pack(msg, compression) |
| 1729 | } |
| 1730 | |
| 1731 | func unpackCNAMEResource(msg []byte, off int) (CNAMEResource, error) { |
| 1732 | var cname Name |
| 1733 | if _, err := cname.unpack(msg, off); err != nil { |
| 1734 | return CNAMEResource{}, err |
| 1735 | } |
| 1736 | return CNAMEResource{cname}, nil |
| 1737 | } |
| 1738 | |
| 1739 | // An MXResource is an MX Resource record. |
| 1740 | type MXResource struct { |
| 1741 | Pref uint16 |
| 1742 | MX Name |
| 1743 | } |
| 1744 | |
| 1745 | func (r *MXResource) realType() Type { |
| 1746 | return TypeMX |
| 1747 | } |
| 1748 | |
| 1749 | func (r *MXResource) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1750 | oldMsg := msg |
| 1751 | msg = packUint16(msg, r.Pref) |
| 1752 | msg, err := r.MX.pack(msg, compression) |
| 1753 | if err != nil { |
| 1754 | return oldMsg, &nestedError{"MXResource.MX", err} |
| 1755 | } |
| 1756 | return msg, nil |
| 1757 | } |
| 1758 | |
| 1759 | func unpackMXResource(msg []byte, off int) (MXResource, error) { |
| 1760 | pref, off, err := unpackUint16(msg, off) |
| 1761 | if err != nil { |
| 1762 | return MXResource{}, &nestedError{"Pref", err} |
| 1763 | } |
| 1764 | var mx Name |
| 1765 | if _, err := mx.unpack(msg, off); err != nil { |
| 1766 | return MXResource{}, &nestedError{"MX", err} |
| 1767 | } |
| 1768 | return MXResource{pref, mx}, nil |
| 1769 | } |
| 1770 | |
| 1771 | // An NSResource is an NS Resource record. |
| 1772 | type NSResource struct { |
| 1773 | NS Name |
| 1774 | } |
| 1775 | |
| 1776 | func (r *NSResource) realType() Type { |
| 1777 | return TypeNS |
| 1778 | } |
| 1779 | |
| 1780 | func (r *NSResource) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1781 | return r.NS.pack(msg, compression) |
| 1782 | } |
| 1783 | |
| 1784 | func unpackNSResource(msg []byte, off int) (NSResource, error) { |
| 1785 | var ns Name |
| 1786 | if _, err := ns.unpack(msg, off); err != nil { |
| 1787 | return NSResource{}, err |
| 1788 | } |
| 1789 | return NSResource{ns}, nil |
| 1790 | } |
| 1791 | |
| 1792 | // A PTRResource is a PTR Resource record. |
| 1793 | type PTRResource struct { |
| 1794 | PTR Name |
| 1795 | } |
| 1796 | |
| 1797 | func (r *PTRResource) realType() Type { |
| 1798 | return TypePTR |
| 1799 | } |
| 1800 | |
| 1801 | func (r *PTRResource) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1802 | return r.PTR.pack(msg, compression) |
| 1803 | } |
| 1804 | |
| 1805 | func unpackPTRResource(msg []byte, off int) (PTRResource, error) { |
| 1806 | var ptr Name |
| 1807 | if _, err := ptr.unpack(msg, off); err != nil { |
| 1808 | return PTRResource{}, err |
| 1809 | } |
| 1810 | return PTRResource{ptr}, nil |
| 1811 | } |
| 1812 | |
| 1813 | // An SOAResource is an SOA Resource record. |
| 1814 | type SOAResource struct { |
| 1815 | NS Name |
| 1816 | MBox Name |
| 1817 | Serial uint32 |
| 1818 | Refresh uint32 |
| 1819 | Retry uint32 |
| 1820 | Expire uint32 |
| 1821 | |
| 1822 | // MinTTL the is the default TTL of Resources records which did not |
| 1823 | // contain a TTL value and the TTL of negative responses. (RFC 2308 |
| 1824 | // Section 4) |
| 1825 | MinTTL uint32 |
| 1826 | } |
| 1827 | |
| 1828 | func (r *SOAResource) realType() Type { |
| 1829 | return TypeSOA |
| 1830 | } |
| 1831 | |
| 1832 | func (r *SOAResource) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1833 | oldMsg := msg |
| 1834 | msg, err := r.NS.pack(msg, compression) |
| 1835 | if err != nil { |
| 1836 | return oldMsg, &nestedError{"SOAResource.NS", err} |
| 1837 | } |
| 1838 | msg, err = r.MBox.pack(msg, compression) |
| 1839 | if err != nil { |
| 1840 | return oldMsg, &nestedError{"SOAResource.MBox", err} |
| 1841 | } |
| 1842 | msg = packUint32(msg, r.Serial) |
| 1843 | msg = packUint32(msg, r.Refresh) |
| 1844 | msg = packUint32(msg, r.Retry) |
| 1845 | msg = packUint32(msg, r.Expire) |
| 1846 | return packUint32(msg, r.MinTTL), nil |
| 1847 | } |
| 1848 | |
| 1849 | func unpackSOAResource(msg []byte, off int) (SOAResource, error) { |
| 1850 | var ns Name |
| 1851 | off, err := ns.unpack(msg, off) |
| 1852 | if err != nil { |
| 1853 | return SOAResource{}, &nestedError{"NS", err} |
| 1854 | } |
| 1855 | var mbox Name |
| 1856 | if off, err = mbox.unpack(msg, off); err != nil { |
| 1857 | return SOAResource{}, &nestedError{"MBox", err} |
| 1858 | } |
| 1859 | serial, off, err := unpackUint32(msg, off) |
| 1860 | if err != nil { |
| 1861 | return SOAResource{}, &nestedError{"Serial", err} |
| 1862 | } |
| 1863 | refresh, off, err := unpackUint32(msg, off) |
| 1864 | if err != nil { |
| 1865 | return SOAResource{}, &nestedError{"Refresh", err} |
| 1866 | } |
| 1867 | retry, off, err := unpackUint32(msg, off) |
| 1868 | if err != nil { |
| 1869 | return SOAResource{}, &nestedError{"Retry", err} |
| 1870 | } |
| 1871 | expire, off, err := unpackUint32(msg, off) |
| 1872 | if err != nil { |
| 1873 | return SOAResource{}, &nestedError{"Expire", err} |
| 1874 | } |
| 1875 | minTTL, _, err := unpackUint32(msg, off) |
| 1876 | if err != nil { |
| 1877 | return SOAResource{}, &nestedError{"MinTTL", err} |
| 1878 | } |
| 1879 | return SOAResource{ns, mbox, serial, refresh, retry, expire, minTTL}, nil |
| 1880 | } |
| 1881 | |
| 1882 | // A TXTResource is a TXT Resource record. |
| 1883 | type TXTResource struct { |
| 1884 | Txt string // Not a domain name. |
| 1885 | } |
| 1886 | |
| 1887 | func (r *TXTResource) realType() Type { |
| 1888 | return TypeTXT |
| 1889 | } |
| 1890 | |
| 1891 | func (r *TXTResource) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1892 | return packText(msg, r.Txt), nil |
| 1893 | } |
| 1894 | |
| 1895 | func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) { |
| 1896 | var txt string |
| 1897 | for n := uint16(0); n < length; { |
| 1898 | var t string |
| 1899 | var err error |
| 1900 | if t, off, err = unpackText(msg, off); err != nil { |
| 1901 | return TXTResource{}, &nestedError{"text", err} |
| 1902 | } |
| 1903 | // Check if we got too many bytes. |
| 1904 | if length-n < uint16(len(t))+1 { |
| 1905 | return TXTResource{}, errCalcLen |
| 1906 | } |
| 1907 | n += uint16(len(t)) + 1 |
| 1908 | txt += t |
| 1909 | } |
| 1910 | return TXTResource{txt}, nil |
| 1911 | } |
| 1912 | |
| 1913 | // An SRVResource is an SRV Resource record. |
| 1914 | type SRVResource struct { |
| 1915 | Priority uint16 |
| 1916 | Weight uint16 |
| 1917 | Port uint16 |
| 1918 | Target Name // Not compressed as per RFC 2782. |
| 1919 | } |
| 1920 | |
| 1921 | func (r *SRVResource) realType() Type { |
| 1922 | return TypeSRV |
| 1923 | } |
| 1924 | |
| 1925 | func (r *SRVResource) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1926 | oldMsg := msg |
| 1927 | msg = packUint16(msg, r.Priority) |
| 1928 | msg = packUint16(msg, r.Weight) |
| 1929 | msg = packUint16(msg, r.Port) |
| 1930 | msg, err := r.Target.pack(msg, nil) |
| 1931 | if err != nil { |
| 1932 | return oldMsg, &nestedError{"SRVResource.Target", err} |
| 1933 | } |
| 1934 | return msg, nil |
| 1935 | } |
| 1936 | |
| 1937 | func unpackSRVResource(msg []byte, off int) (SRVResource, error) { |
| 1938 | priority, off, err := unpackUint16(msg, off) |
| 1939 | if err != nil { |
| 1940 | return SRVResource{}, &nestedError{"Priority", err} |
| 1941 | } |
| 1942 | weight, off, err := unpackUint16(msg, off) |
| 1943 | if err != nil { |
| 1944 | return SRVResource{}, &nestedError{"Weight", err} |
| 1945 | } |
| 1946 | port, off, err := unpackUint16(msg, off) |
| 1947 | if err != nil { |
| 1948 | return SRVResource{}, &nestedError{"Port", err} |
| 1949 | } |
| 1950 | var target Name |
| 1951 | if _, err := target.unpack(msg, off); err != nil { |
| 1952 | return SRVResource{}, &nestedError{"Target", err} |
| 1953 | } |
| 1954 | return SRVResource{priority, weight, port, target}, nil |
| 1955 | } |
| 1956 | |
| 1957 | // An AResource is an A Resource record. |
| 1958 | type AResource struct { |
| 1959 | A [4]byte |
| 1960 | } |
| 1961 | |
| 1962 | func (r *AResource) realType() Type { |
| 1963 | return TypeA |
| 1964 | } |
| 1965 | |
| 1966 | func (r *AResource) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1967 | return packBytes(msg, r.A[:]), nil |
| 1968 | } |
| 1969 | |
| 1970 | func unpackAResource(msg []byte, off int) (AResource, error) { |
| 1971 | var a [4]byte |
| 1972 | if _, err := unpackBytes(msg, off, a[:]); err != nil { |
| 1973 | return AResource{}, err |
| 1974 | } |
| 1975 | return AResource{a}, nil |
| 1976 | } |
| 1977 | |
| 1978 | // An AAAAResource is an AAAA Resource record. |
| 1979 | type AAAAResource struct { |
| 1980 | AAAA [16]byte |
| 1981 | } |
| 1982 | |
| 1983 | func (r *AAAAResource) realType() Type { |
| 1984 | return TypeAAAA |
| 1985 | } |
| 1986 | |
| 1987 | func (r *AAAAResource) pack(msg []byte, compression map[string]int) ([]byte, error) { |
| 1988 | return packBytes(msg, r.AAAA[:]), nil |
| 1989 | } |
| 1990 | |
| 1991 | func unpackAAAAResource(msg []byte, off int) (AAAAResource, error) { |
| 1992 | var aaaa [16]byte |
| 1993 | if _, err := unpackBytes(msg, off, aaaa[:]); err != nil { |
| 1994 | return AAAAResource{}, err |
| 1995 | } |
| 1996 | return AAAAResource{aaaa}, nil |
| 1997 | } |