domain_core/iana/rcode.rs
1//! DNS response codes and extended response codes.
2//!
3//! The original DNS specification in [RFC 1035] specified four bits of the
4//! message header as response code. The type [Rcode] defined herein
5//! represents these codes. Later, [RFC 2671][] (now [RFC 6891]) added eight
6//! bits to the response code to be transmitted as part of the OPT
7//! pseudo-resource record. To make matters even worse, the TSIG and TKEY
8//! records defined by [RFC 2845] and [RFC 2930] use a 16 bit error code.
9//! All of these codes share the same defition space. Even so, we have
10//! separate types for each of these.
11//!
12//! [Rcode]: enum.Rcode.html
13//! [RFC 1035]: https://tools.ietf.org/html/rfc1035
14//! [RFC 2671]: https://tools.ietf.org/html/rfc2671
15//! [RFC 2845]: https://tools.ietf.org/html/rfc2845
16//! [RFC 2930]: https://tools.ietf.org/html/rfc2930
17//! [RFC 6891]: https://tools.ietf.org/html/rfc6891
18//!
19
20use std::cmp;
21use std::fmt;
22use std::hash;
23
24
25//------------ Rcode --------------------------------------------------------
26
27/// DNS Response Codes.
28///
29/// The response code of a response indicates what happend on the server
30/// when trying to answer the query. The code is a 4 bit value and part of
31/// the header of a DNS message.
32///
33/// This response was defined as part of [RFC 1035]. Later, [RFC 2671]
34/// defined an extended response code of 12 bits using the lower four bits
35/// from the header and eight additional bits stored in the OPT
36/// pseudo-record. The type [OptRcode] represents this extended response
37/// code. A third response code, now 16 bit wide, was defined for the
38/// transaction authentication mechansim (TSIG) in [RFC 2845] and is
39/// represented by [TsigRcode].
40///
41/// All three codes share the same name space. Their values are defined in
42/// one registry, [IANA DNS RCODEs]. This type is complete as of 2019-01-28.
43///
44/// [OptRcode]: enum.OptRcode.html
45/// [TsigRcode]: enum.TsigRcode.html
46/// [IANA DNS RCODEs]: http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
47/// [RFC 1035]: https://tools.ietf.org/html/rfc1035
48/// [RFC 2671]: https://tools.ietf.org/html/rfc2671
49#[derive(Clone, Copy, Debug)]
50pub enum Rcode {
51 /// No error condition.
52 ///
53 /// (Otherwise known as success.)
54 ///
55 /// Defined in [RFC 1035].
56 ///
57 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
58 NoError,
59
60 /// Format error.
61 ///
62 /// The name server was unable to interpret the query.
63 ///
64 /// Defined in [RFC 1035].
65 ///
66 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
67 FormErr,
68
69 /// Server failure.
70 ///
71 /// The name server was unable to process this query due to a problem
72 /// with the name server.
73 ///
74 /// Defined in [RFC 1035].
75 ///
76 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
77 ServFail,
78
79 /// Name error.
80 ///
81 /// The domain name given in the query does not exist at the name server.
82 ///
83 /// Defined in [RFC 1035].
84 ///
85 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
86 NXDomain,
87
88 /// Not implemented.
89 ///
90 /// The name server does not support the requested kind of query.
91 ///
92 /// Defined in [RFC 1035].
93 ///
94 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
95 NotImp,
96
97 /// Query refused.
98 ///
99 /// The name server refused to perform the operation requested by the
100 /// query for policy reasons.
101 ///
102 /// Defined in [RFC 1035].
103 ///
104 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
105 Refused,
106
107 /// Name exists when it should not.
108 ///
109 /// Returned for an UPDATE query when a domain requested to not exist
110 /// does in fact exist.
111 ///
112 /// Returned when resolving a DNAME redirection when the resulting name
113 /// exceeds the length of 255 octets.
114 ///
115 /// Defined in [RFC 2136] for the UPDATE query and [RFC 6672] for DNAME
116 /// redirection.
117 ///
118 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
119 /// [RFC 6672]: https://tools.ietf.org/html/rfc6672
120 YXDomain,
121
122 /// RR set exists when it should not.
123 ///
124 /// Returned for an UPDATE query when an RRset requested to not exist
125 /// does in fact exist.
126 ///
127 /// Defined in [RFC 2136].
128 ///
129 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
130 YXRRSet,
131
132 /// RR set that should exist does not.
133 ///
134 /// Returned for an UPDATE query when an RRset requested to exist
135 /// does not.
136 ///
137 /// Defined in [RFC 2136].
138 ///
139 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
140 NXRRSet,
141
142 /// Server not authoritative for zone or client not authorized.
143 ///
144 /// Returned for an UPDATE query when the server is not an authoritative
145 /// name server for the requested domain.
146 ///
147 /// Returned for queries using TSIG when authorisation failed.
148 ///
149 /// Defined in [RFC 2136] for UPDATE and [RFC 2845] for TSIG.
150 ///
151 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
152 /// [RFC 2845]: https://tools.ietf.org/html/rfc2845
153 NotAuth,
154
155 /// Name not contained in zone.
156 ///
157 /// A name used in the prerequisite or update section is not within the
158 /// zone given in the zone section.
159 ///
160 /// Defined in [RFC 2136].
161 ///
162 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
163 NotZone,
164
165 /// A raw, integer rcode value.
166 ///
167 /// When converting to an `u8`, only the lower four bits are used.
168 Int(u8)
169}
170
171impl Rcode {
172 /// Creates an rcode from an integer.
173 ///
174 /// Only the lower four bits of `value` are considered.
175 pub fn from_int(value: u8) -> Rcode {
176 use self::Rcode::*;
177
178 match value & 0x0F {
179 0 => NoError,
180 1 => FormErr,
181 2 => ServFail,
182 3 => NXDomain,
183 4 => NotImp,
184 5 => Refused,
185 6 => YXDomain,
186 7 => YXRRSet,
187 8 => NXRRSet,
188 9 => NotAuth,
189 10 => NotZone,
190 value => Int(value)
191 }
192 }
193
194 /// Returns the integer value for this rcode.
195 pub fn to_int(self) -> u8 {
196 use self::Rcode::*;
197
198 match self {
199 NoError => 0,
200 FormErr => 1,
201 ServFail => 2,
202 NXDomain => 3,
203 NotImp => 4,
204 Refused => 5,
205 YXDomain => 6,
206 YXRRSet => 7,
207 NXRRSet => 8,
208 NotAuth => 9,
209 NotZone => 10,
210 Int(value) => value & 0x0F
211 }
212 }
213}
214
215
216//--- From
217
218impl From<u8> for Rcode {
219 fn from(value: u8) -> Rcode { Rcode::from_int(value) }
220}
221
222impl From<Rcode> for u8 {
223 fn from(value: Rcode) -> u8 { value.to_int() }
224}
225
226
227//--- Display
228
229impl fmt::Display for Rcode {
230 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
231 use self::Rcode::*;
232
233 match *self {
234 NoError => "NOERROR".fmt(f),
235 FormErr => "FORMERR".fmt(f),
236 ServFail => "SERVFAIL".fmt(f),
237 NXDomain => "NXDOMAIN".fmt(f),
238 NotImp => "NOTIMP".fmt(f),
239 Refused => "REFUSED".fmt(f),
240 YXDomain => "YXDOMAIN".fmt(f),
241 YXRRSet => "YXRRSET".fmt(f),
242 NXRRSet => "NXRRSET".fmt(f),
243 NotAuth => "NOAUTH".fmt(f),
244 NotZone => "NOTZONE".fmt(f),
245 Int(i) => {
246 match Rcode::from_int(i) {
247 Rcode::Int(i) => i.fmt(f),
248 value => value.fmt(f)
249 }
250 }
251 }
252 }
253}
254
255
256//--- PartialEq and Eq
257
258impl cmp::PartialEq for Rcode {
259 fn eq(&self, other: &Rcode) -> bool {
260 self.to_int() == other.to_int()
261 }
262}
263
264impl cmp::PartialEq<u8> for Rcode {
265 fn eq(&self, other: &u8) -> bool {
266 self.to_int() == *other
267 }
268}
269
270impl cmp::PartialEq<Rcode> for u8 {
271 fn eq(&self, other: &Rcode) -> bool {
272 *self == other.to_int()
273 }
274}
275
276impl cmp::Eq for Rcode { }
277
278
279//--- PartialOrd and Ord
280
281impl cmp::PartialOrd for Rcode {
282 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
283 self.to_int().partial_cmp(&other.to_int())
284 }
285}
286
287impl cmp::PartialOrd<u8> for Rcode {
288 fn partial_cmp(&self, other: &u8) -> Option<cmp::Ordering> {
289 self.to_int().partial_cmp(other)
290 }
291}
292
293impl cmp::PartialOrd<Rcode> for u8 {
294 fn partial_cmp(&self, other: &Rcode) -> Option<cmp::Ordering> {
295 self.partial_cmp(&other.to_int())
296 }
297}
298
299impl cmp::Ord for Rcode {
300 fn cmp(&self, other: &Rcode) -> cmp::Ordering {
301 self.to_int().cmp(&other.to_int())
302 }
303}
304
305
306//--- Hash
307
308impl hash::Hash for Rcode {
309 fn hash<H: hash::Hasher>(&self, state: &mut H) {
310 self.to_int().hash(state)
311 }
312}
313
314
315//------------ OptRcode -----------------------------------------------------
316
317/// Extended DNS Response Codes for OPT records.
318///
319/// Originally, the response code of embedded in the header of each DNS
320/// message was four bits long. This code, defined in [RFC 1035], is
321/// represented by the [Rcode] type. The extension mechanism for DNS
322/// initially defined in [RFC 2671] and updated by [RFC 6891] added eight
323/// more bits to be stored in the OPT pseudo-resource record. This type
324/// represents the complete 12 bit extended response code.
325///
326/// There is a third, 16 bit wide response code for transaction
327/// authentication (TSIG) defined in [RFC 2845] and represented by the
328/// [`TsigRcode`] type. The code mostly shares the same name space except
329/// for an unfortunate collision in between the BADVERS and BADSIG values.
330/// Because of this, we decided to have separate types.
331///
332/// The values for all three response code types are defined in
333/// the [IANA DNS RCODEs] registry. This type is complete as of 2019-01-28.
334///
335/// [Rcode]: enum.Rcode.html
336/// [`TsigRcode`]: enum.TsigRcode.html
337/// [IANA DNS RCODEs]: http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
338/// [RFC 2671]: https://tools.ietf.org/html/rfc2671
339/// [RFC 2845]: https://tools.ietf.org/html/rfc2845
340/// [RFC 2930]: https://tools.ietf.org/html/rfc2930
341/// [RFC 6891]: https://tools.ietf.org/html/rfc6891
342#[derive(Clone, Copy, Debug)]
343pub enum OptRcode {
344 /// No error condition.
345 ///
346 /// (Otherwise known as success.)
347 ///
348 /// Defined in [RFC 1035].
349 ///
350 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
351 NoError,
352
353 /// Format error.
354 ///
355 /// The name server was unable to interpret the query.
356 ///
357 /// Defined in [RFC 1035].
358 ///
359 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
360 FormErr,
361
362 /// Server failure.
363 ///
364 /// The name server was unable to process this query due to a problem
365 /// with the name server.
366 ///
367 /// Defined in [RFC 1035].
368 ///
369 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
370 ServFail,
371
372 /// Name error.
373 ///
374 /// The domain name given in the query does not exist at the name server.
375 ///
376 /// Defined in [RFC 1035].
377 ///
378 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
379 NXDomain,
380
381 /// Not implemented.
382 ///
383 /// The name server does not support the requested kind of query.
384 ///
385 /// Defined in [RFC 1035].
386 ///
387 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
388 NotImp,
389
390 /// Query refused.
391 ///
392 /// The name server refused to perform the operation requested by the
393 /// query for policy reasons.
394 ///
395 /// Defined in [RFC 1035].
396 ///
397 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
398 Refused,
399
400 /// Name exists when it should not.
401 ///
402 /// Returned for an UPDATE query when a domain requested to not exist
403 /// does in fact exist.
404 ///
405 /// Returned when resolving a DNAME redirection when the resulting name
406 /// exceeds the length of 255 octets.
407 ///
408 /// Defined in [RFC 2136] for the UPDATE query and [RFC 6672] for DNAME
409 /// redirection.
410 ///
411 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
412 /// [RFC 6672]: https://tools.ietf.org/html/rfc6672
413 YXDomain,
414
415 /// RR set exists when it should not.
416 ///
417 /// Returned for an UPDATE query when an RRset requested to not exist
418 /// does in fact exist.
419 ///
420 /// Defined in [RFC 2136].
421 ///
422 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
423 YXRRSet,
424
425 /// RR set that should exist does not.
426 ///
427 /// Returned for an UPDATE query when an RRset requested to exist
428 /// does not.
429 ///
430 /// Defined in [RFC 2136].
431 ///
432 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
433 NXRRSet,
434
435 /// Server not authoritative for zone or client not authorized.
436 ///
437 /// Returned for an UPDATE query when the server is not an authoritative
438 /// name server for the requested domain.
439 ///
440 /// Returned for queries using TSIG when authorisation failed.
441 ///
442 /// Defined in [RFC 2136] for UPDATE and [RFC 2845] for TSIG.
443 ///
444 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
445 /// [RFC 2845]: https://tools.ietf.org/html/rfc2845
446 NotAuth,
447
448 /// Name not contained in zone.
449 ///
450 /// A name used in the prerequisite or update section is not within the
451 /// zone given in the zone section.
452 ///
453 /// Defined in [RFC 2136].
454 ///
455 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
456 NotZone,
457
458 /// Bad OPT version.
459 ///
460 /// A name server does not implement the EDNS version requested in the
461 /// OPT record.
462 ///
463 /// Defined in [RFC 6891].
464 ///
465 /// [RFC 6891]: https://tools.ietf.org/html/rfc6891
466 BadVers,
467
468 // XXX We will not define the values from the TSIG and TKEY RFCs,
469 // unless are used in OPT records, too?
470
471 /// Bad or missing server cookie.
472 ///
473 /// The request contained a COOKIE option either without a server cookie
474 /// or with a server cookie that did not validate.
475 ///
476 /// Defined in [RFC 7873].
477 ///
478 /// [RFC 7873]: https://tools.ietf.org/html/rfc7873
479 BadCookie,
480
481 /// A raw, integer rcode value.
482 ///
483 /// When converting to a 12 bit code, the upper four bits are simply
484 /// ignored.
485 Int(u16)
486}
487
488
489impl OptRcode {
490 /// Creates an rcode from an integer.
491 ///
492 /// Only the lower twelve bits of `value` are considered.
493 pub fn from_int(value: u16) -> OptRcode {
494 use self::OptRcode::*;
495
496 match value & 0x0FFF {
497 0 => NoError,
498 1 => FormErr,
499 2 => ServFail,
500 3 => NXDomain,
501 4 => NotImp,
502 5 => Refused,
503 6 => YXDomain,
504 7 => YXRRSet,
505 8 => NXRRSet,
506 9 => NotAuth,
507 10 => NotZone,
508 16 => BadVers,
509 23 => BadCookie,
510 value => Int(value)
511 }
512 }
513
514 /// Returns the integer value for this rcode.
515 pub fn to_int(self) -> u16 {
516 use self::OptRcode::*;
517
518 match self {
519 NoError => 0,
520 FormErr => 1,
521 ServFail => 2,
522 NXDomain => 3,
523 NotImp => 4,
524 Refused => 5,
525 YXDomain => 6,
526 YXRRSet => 7,
527 NXRRSet => 8,
528 NotAuth => 9,
529 NotZone => 10,
530 BadVers => 16,
531 BadCookie => 23,
532 Int(value) => value & 0x0F
533 }
534 }
535
536 /// Creates an extended rcode value from its parts.
537 pub fn from_parts(rcode: Rcode, ext: u8) -> OptRcode {
538 if ext == 0 {
539 rcode.into()
540 }
541 else {
542 OptRcode::from_int(
543 u16::from(ext) << 4 | u16::from(rcode.to_int())
544 )
545 }
546 }
547
548 /// Returns the two parts of an extended rcode value.
549 pub fn to_parts(self) -> (Rcode, u8) {
550 let res = self.to_int();
551 (Rcode::from_int(res as u8), (res >> 8) as u8)
552 }
553
554 /// Returns the rcode part of the extended rcode.
555 pub fn rcode(self) -> Rcode {
556 self.to_parts().0
557 }
558
559 /// Returns the extended octet of the extended rcode.
560 pub fn ext(self) -> u8 {
561 self.to_parts().1
562 }
563}
564
565
566//--- From
567
568impl From<u16> for OptRcode {
569 fn from(value: u16) -> OptRcode { OptRcode::from_int(value) }
570}
571
572impl From<OptRcode> for u16 {
573 fn from(value: OptRcode) -> u16 { value.to_int() }
574}
575
576impl From<Rcode> for OptRcode {
577 fn from(value: Rcode) -> OptRcode { OptRcode::from_parts(value, 0) }
578}
579
580
581//--- Display
582
583impl fmt::Display for OptRcode {
584 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
585 use self::OptRcode::*;
586
587 match *self {
588 NoError => "NOERROR".fmt(f),
589 FormErr => "FORMERR".fmt(f),
590 ServFail => "SERVFAIL".fmt(f),
591 NXDomain => "NXDOMAIN".fmt(f),
592 NotImp => "NOTIMP".fmt(f),
593 Refused => "REFUSED".fmt(f),
594 YXDomain => "YXDOMAIN".fmt(f),
595 YXRRSet => "YXRRSET".fmt(f),
596 NXRRSet => "NXRRSET".fmt(f),
597 NotAuth => "NOAUTH".fmt(f),
598 NotZone => "NOTZONE".fmt(f),
599 BadVers => "BADVER".fmt(f),
600 BadCookie => "BADCOOKIE".fmt(f),
601 Int(i) => {
602 match OptRcode::from_int(i) {
603 Int(i) => i.fmt(f),
604 value => value.fmt(f)
605 }
606 }
607 }
608 }
609}
610
611
612
613//------------ TsigRcode ----------------------------------------------------
614
615/// Response codes for transaction authentication (TSIG).
616///
617/// TSIG and TKEY resource records contain a 16 bit wide error field whose
618/// values are an extension of the standard DNS [`Rcode`]. While it was
619/// intended to also share the same space with the extended response codes
620/// used by EDNS (see [`OptRcode`]), both used the value 16. To allow
621/// distinguish between the two uses of this value, we have two separate
622/// types.
623///
624/// The values for all three response code types are defined in
625/// the [IANA DNS RCODEs] registry. This type is complete as of 2019-01-28.
626///
627/// [`Rcode`]: enum.Rcode.html
628/// [`OptRcode`]: enum.OptRcode.html
629/// [IANA DNS RCODEs]: http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
630#[derive(Clone, Copy, Debug)]
631pub enum TsigRcode {
632 /// No error condition.
633 ///
634 /// (Otherwise known as success.)
635 ///
636 /// Defined in [RFC 1035].
637 ///
638 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
639 NoError,
640
641 /// Format error.
642 ///
643 /// The name server was unable to interpret the query.
644 ///
645 /// Defined in [RFC 1035].
646 ///
647 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
648 FormErr,
649
650 /// Server failure.
651 ///
652 /// The name server was unable to process this query due to a problem
653 /// with the name server.
654 ///
655 /// Defined in [RFC 1035].
656 ///
657 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
658 ServFail,
659
660 /// Name error.
661 ///
662 /// The domain name given in the query does not exist at the name server.
663 ///
664 /// Defined in [RFC 1035].
665 ///
666 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
667 NXDomain,
668
669 /// Not implemented.
670 ///
671 /// The name server does not support the requested kind of query.
672 ///
673 /// Defined in [RFC 1035].
674 ///
675 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
676 NotImp,
677
678 /// Query refused.
679 ///
680 /// The name server refused to perform the operation requested by the
681 /// query for policy reasons.
682 ///
683 /// Defined in [RFC 1035].
684 ///
685 /// [RFC 1035]: https://tools.ietf.org/html/rfc1035
686 Refused,
687
688 /// Name exists when it should not.
689 ///
690 /// Returned for an UPDATE query when a domain requested to not exist
691 /// does in fact exist.
692 ///
693 /// Returned when resolving a DNAME redirection when the resulting name
694 /// exceeds the length of 255 octets.
695 ///
696 /// Defined in [RFC 2136] for the UPDATE query and [RFC 6672] for DNAME
697 /// redirection.
698 ///
699 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
700 /// [RFC 6672]: https://tools.ietf.org/html/rfc6672
701 YXDomain,
702
703 /// RR set exists when it should not.
704 ///
705 /// Returned for an UPDATE query when an RRset requested to not exist
706 /// does in fact exist.
707 ///
708 /// Defined in [RFC 2136].
709 ///
710 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
711 YXRRSet,
712
713 /// RR set that should exist does not.
714 ///
715 /// Returned for an UPDATE query when an RRset requested to exist
716 /// does not.
717 ///
718 /// Defined in [RFC 2136].
719 ///
720 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
721 NXRRSet,
722
723 /// Server not authoritative for zone or client not authorized.
724 ///
725 /// Returned for an UPDATE query when the server is not an authoritative
726 /// name server for the requested domain.
727 ///
728 /// Returned for queries using TSIG when authorisation failed.
729 ///
730 /// Defined in [RFC 2136] for UPDATE and [RFC 2845] for TSIG.
731 ///
732 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
733 /// [RFC 2845]: https://tools.ietf.org/html/rfc2845
734 NotAuth,
735
736 /// Name not contained in zone.
737 ///
738 /// A name used in the prerequisite or update section is not within the
739 /// zone given in the zone section.
740 ///
741 /// Defined in [RFC 2136].
742 ///
743 /// [RFC 2136]: https://tools.ietf.org/html/rfc2136
744 NotZone,
745
746 /// TSIG signature failure.
747 ///
748 /// The TSIG signature fails to verify.
749 ///
750 /// Defined in [RFC 2845].
751 ///
752 /// [RFC 2845]: https://tools.ietf.org/html/rfc2845
753 BadSig,
754
755 /// Key not recognized.
756 ///
757 /// The server did not recognize the key used for generating the
758 /// signature.
759 ///
760 /// Defined in [RFC 2845].
761 ///
762 /// [RFC 2845]: https://tools.ietf.org/html/rfc2845
763 BadKey,
764
765 /// Signature out of time window.
766 ///
767 /// The server time was outside the time interval specified by the
768 /// request.
769 ///
770 /// Defined in [RFC 2845].
771 ///
772 /// [RFC 2845]: https://tools.ietf.org/html/rfc2845
773 BadTime,
774
775 /// Bad TKEY mode.
776 ///
777 /// The mode field in a TKEY resource record contained a mode not
778 /// supported by the server.
779 ///
780 /// Defined in [RFC 2930].
781 ///
782 /// [RFC 2930]: https://tools.ietf.org/html/rfc2930
783 BadMode,
784
785 /// Duplicate key name.
786 ///
787 /// In TKEY records, when establishing a new key, the name used already
788 /// exists at the server or when deleting a key, a key of this name does
789 /// not exist.
790 ///
791 /// Defined in [RFC 2930].
792 ///
793 /// [RFC 2930]: https://tools.ietf.org/html/rfc2930
794 BadName,
795
796 /// Algorithm not supported.
797 ///
798 /// The value is defined in [RFC 2930] but never actually explained.
799 /// Presumably, it will be returned when the algorithm field of a TKEY
800 /// record contains a value not supported by the server.
801 ///
802 /// [RFC 2930]: https://tools.ietf.org/html/rfc2930
803 BadAlg,
804
805 /// Bad truncation.
806 ///
807 /// A TSIG record was received with a MAC too short for the local
808 /// policy in force.
809 ///
810 /// Defined in [RFC 4635].
811 ///
812 /// [RFC 4635]: https://tools.ietf.org/html/rfc4635
813 BadTrunc,
814
815 /// Bad or missing server cookie.
816 ///
817 /// The request contained a COOKIE option either without a server cookie
818 /// or with a server cookie that did not validate.
819 ///
820 /// Defined in [RFC 7873].
821 ///
822 /// [RFC 7873]: https://tools.ietf.org/html/rfc7873
823 BadCookie,
824
825 /// A raw, integer rcode value.
826 ///
827 /// When converting to a 12 bit code, the upper four bits are simply
828 /// ignored.
829 Int(u16)
830}
831
832
833impl TsigRcode {
834 /// Creates an rcode from an integer.
835 pub fn from_int(value: u16) -> TsigRcode {
836 use self::TsigRcode::*;
837
838 match value {
839 0 => NoError,
840 1 => FormErr,
841 2 => ServFail,
842 3 => NXDomain,
843 4 => NotImp,
844 5 => Refused,
845 6 => YXDomain,
846 7 => YXRRSet,
847 8 => NXRRSet,
848 9 => NotAuth,
849 10 => NotZone,
850 16 => BadSig,
851 17 => BadKey,
852 18 => BadTime,
853 19 => BadMode,
854 20 => BadName,
855 21 => BadAlg,
856 22 => BadTrunc,
857 23 => BadCookie,
858 value => Int(value)
859 }
860 }
861
862 /// Returns the integer value for this rcode.
863 pub fn to_int(self) -> u16 {
864 use self::TsigRcode::*;
865
866 match self {
867 NoError => 0,
868 FormErr => 1,
869 ServFail => 2,
870 NXDomain => 3,
871 NotImp => 4,
872 Refused => 5,
873 YXDomain => 6,
874 YXRRSet => 7,
875 NXRRSet => 8,
876 NotAuth => 9,
877 NotZone => 10,
878 BadSig => 16,
879 BadKey => 17,
880 BadTime => 18,
881 BadMode => 19,
882 BadName => 20,
883 BadAlg => 21,
884 BadTrunc => 22,
885 BadCookie => 23,
886 Int(value) => value & 0x0F
887 }
888 }
889}
890
891
892//--- From
893
894impl From<u16> for TsigRcode {
895 fn from(value: u16) -> TsigRcode { TsigRcode::from_int(value) }
896}
897
898impl From<TsigRcode> for u16 {
899 fn from(value: TsigRcode) -> u16 { value.to_int() }
900}
901
902impl From<Rcode> for TsigRcode {
903 fn from(value: Rcode) -> TsigRcode {
904 TsigRcode::from_int(u16::from(value.to_int()))
905 }
906}
907
908impl From<OptRcode> for TsigRcode {
909 fn from(value: OptRcode) -> TsigRcode {
910 TsigRcode::from_int(value.to_int())
911 }
912}
913
914
915//--- Display
916
917impl fmt::Display for TsigRcode {
918 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
919 use self::TsigRcode::*;
920
921 match *self {
922 NoError => "NOERROR".fmt(f),
923 FormErr => "FORMERR".fmt(f),
924 ServFail => "SERVFAIL".fmt(f),
925 NXDomain => "NXDOMAIN".fmt(f),
926 NotImp => "NOTIMP".fmt(f),
927 Refused => "REFUSED".fmt(f),
928 YXDomain => "YXDOMAIN".fmt(f),
929 YXRRSet => "YXRRSET".fmt(f),
930 NXRRSet => "NXRRSET".fmt(f),
931 NotAuth => "NOAUTH".fmt(f),
932 NotZone => "NOTZONE".fmt(f),
933 BadSig => "BADSIG".fmt(f),
934 BadKey => "BADKEY".fmt(f),
935 BadTime => "BADTIME".fmt(f),
936 BadMode => "BADMODE".fmt(f),
937 BadName => "BADNAME".fmt(f),
938 BadAlg => "BADALG".fmt(f),
939 BadTrunc => "BADTRUNC".fmt(f),
940 BadCookie => "BADCOOKIE".fmt(f),
941 Int(i) => {
942 match TsigRcode::from_int(i) {
943 Int(i) => i.fmt(f),
944 value => value.fmt(f)
945 }
946 }
947 }
948 }
949}
950