s4-python: Move dnspython to lib/, like the other Python modules
[samba.git] / lib / dnspython / dns / rcode.py
1 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
2 #
3 # Permission to use, copy, modify, and distribute this software and its
4 # documentation for any purpose with or without fee is hereby granted,
5 # provided that the above copyright notice and this permission notice
6 # appear in all copies.
7 #
8 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
9 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
11 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
16 """DNS Result Codes."""
17
18 import dns.exception
19
20 NOERROR = 0
21 FORMERR = 1
22 SERVFAIL = 2
23 NXDOMAIN = 3
24 NOTIMP = 4
25 REFUSED = 5
26 YXDOMAIN = 6
27 YXRRSET = 7
28 NXRRSET = 8
29 NOTAUTH = 9
30 NOTZONE = 10
31 BADVERS = 16
32
33 _by_text = {
34     'NOERROR' : NOERROR,
35     'FORMERR' : FORMERR,
36     'SERVFAIL' : SERVFAIL,
37     'NXDOMAIN' : NXDOMAIN,
38     'NOTIMP' : NOTIMP,
39     'REFUSED' : REFUSED,
40     'YXDOMAIN' : YXDOMAIN,
41     'YXRRSET' : YXRRSET,
42     'NXRRSET' : NXRRSET,
43     'NOTAUTH' : NOTAUTH,
44     'NOTZONE' : NOTZONE,
45     'BADVERS' : BADVERS
46 }
47
48 # We construct the inverse mapping programmatically to ensure that we
49 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
50 # would cause the mapping not to be a true inverse.
51
52 _by_value = dict([(y, x) for x, y in _by_text.iteritems()])
53
54
55 class UnknownRcode(dns.exception.DNSException):
56     """Raised if an rcode is unknown."""
57     pass
58
59 def from_text(text):
60     """Convert text into an rcode.
61
62     @param text: the texual rcode
63     @type text: string
64     @raises UnknownRcode: the rcode is unknown
65     @rtype: int
66     """
67
68     if text.isdigit():
69         v = int(text)
70         if v >= 0 and v <= 4095:
71             return v
72     v = _by_text.get(text.upper())
73     if v is None:
74         raise UnknownRcode
75     return v
76
77 def from_flags(flags, ednsflags):
78     """Return the rcode value encoded by flags and ednsflags.
79
80     @param flags: the DNS flags
81     @type flags: int
82     @param ednsflags: the EDNS flags
83     @type ednsflags: int
84     @raises ValueError: rcode is < 0 or > 4095
85     @rtype: int
86     """
87
88     value = (flags & 0x000f) | ((ednsflags >> 20) & 0xff0)
89     if value < 0 or value > 4095:
90         raise ValueError('rcode must be >= 0 and <= 4095')
91     return value
92
93 def to_flags(value):
94     """Return a (flags, ednsflags) tuple which encodes the rcode.
95
96     @param value: the rcode
97     @type value: int
98     @raises ValueError: rcode is < 0 or > 4095
99     @rtype: (int, int) tuple
100     """
101
102     if value < 0 or value > 4095:
103         raise ValueError('rcode must be >= 0 and <= 4095')
104     v = value & 0xf
105     ev = long(value & 0xff0) << 20
106     return (v, ev)
107
108 def to_text(value):
109     """Convert rcode into text.
110
111     @param value: the rcode
112     @type value: int
113     @rtype: string
114     """
115
116     text = _by_value.get(value)
117     if text is None:
118         text = str(value)
119     return text