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
43globals().update(Opcode.__members__)
44
45
46class UnknownOpcode(dns.exception.DNSException):
47    """An DNS opcode is unknown."""
48
49
50def from_text(text):
51    """Convert text into an opcode.
52
53    *text*, a ``str``, the textual opcode
54
55    Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown.
56
57    Returns an ``int``.
58    """
59
60    return Opcode.from_text(text)
61
62
63def from_flags(flags):
64    """Extract an opcode from DNS message flags.
65
66    *flags*, an ``int``, the DNS flags.
67
68    Returns an ``int``.
69    """
70
71    return (flags & 0x7800) >> 11
72
73
74def to_flags(value):
75    """Convert an opcode to a value suitable for ORing into DNS message
76    flags.
77
78    *value*, an ``int``, the DNS opcode value.
79
80    Returns an ``int``.
81    """
82
83    return (value << 11) & 0x7800
84
85
86def to_text(value):
87    """Convert an opcode to text.
88
89    *value*, an ``int`` the opcode value,
90
91    Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown.
92
93    Returns a ``str``.
94    """
95
96    return Opcode.to_text(value)
97
98
99def is_update(flags):
100    """Is the opcode in flags UPDATE?
101
102    *flags*, an ``int``, the DNS message flags.
103
104    Returns a ``bool``.
105    """
106
107    return from_flags(flags) == Opcode.UPDATE
108