1# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
2
3# Copyright (C) 2001-2017 Nominum, Inc.
4#
5# Permission to use, copy, modify, and distribute this software and its
6# documentation for any purpose with or without fee is hereby granted,
7# provided that the above copyright notice and this permission notice
8# appear in all copies.
9#
10# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18"""DNS Opcodes."""
19
20import dns.enum
21import dns.exception
22
23class Opcode(dns.enum.IntEnum):
24    #: Query
25    QUERY = 0
26    #: Inverse Query (historical)
27    IQUERY = 1
28    #: Server Status (unspecified and unimplemented anywhere)
29    STATUS = 2
30    #: Notify
31    NOTIFY = 4
32    #: Dynamic Update
33    UPDATE = 5
34
35    @classmethod
36    def _maximum(cls):
37        return 15
38
39    @classmethod
40    def _unknown_exception_class(cls):
41        return UnknownOpcode
42
43
44class UnknownOpcode(dns.exception.DNSException):
45    """An DNS opcode is unknown."""
46
47
48def from_text(text):
49    """Convert text into an opcode.
50
51    *text*, a ``str``, the textual opcode
52
53    Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown.
54
55    Returns an ``int``.
56    """
57
58    return Opcode.from_text(text)
59
60
61def from_flags(flags):
62    """Extract an opcode from DNS message flags.
63
64    *flags*, an ``int``, the DNS flags.
65
66    Returns an ``int``.
67    """
68
69    return (flags & 0x7800) >> 11
70
71
72def to_flags(value):
73    """Convert an opcode to a value suitable for ORing into DNS message
74    flags.
75
76    *value*, an ``int``, the DNS opcode value.
77
78    Returns an ``int``.
79    """
80
81    return (value << 11) & 0x7800
82
83
84def to_text(value):
85    """Convert an opcode to text.
86
87    *value*, an ``int`` the opcode value,
88
89    Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown.
90
91    Returns a ``str``.
92    """
93
94    return Opcode.to_text(value)
95
96
97def is_update(flags):
98    """Is the opcode in flags UPDATE?
99
100    *flags*, an ``int``, the DNS message flags.
101
102    Returns a ``bool``.
103    """
104
105    return from_flags(flags) == Opcode.UPDATE
106
107### BEGIN generated Opcode constants
108
109QUERY = Opcode.QUERY
110IQUERY = Opcode.IQUERY
111STATUS = Opcode.STATUS
112NOTIFY = Opcode.NOTIFY
113UPDATE = Opcode.UPDATE
114
115### END generated Opcode constants
116