Package dns :: Package rdtypes :: Package IN :: Module APL
[hide private]
[frames] | no frames]

Source Code for Module dns.rdtypes.IN.APL

  1  # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 
  2   
  3  # Copyright (C) 2003-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  import binascii 
 19  import codecs 
 20  import struct 
 21   
 22  import dns.exception 
 23  import dns.inet 
 24  import dns.rdata 
 25  import dns.tokenizer 
 26  from dns._compat import xrange, maybe_chr 
27 28 29 -class APLItem(object):
30 31 """An APL list item. 32 33 @ivar family: the address family (IANA address family registry) 34 @type family: int 35 @ivar negation: is this item negated? 36 @type negation: bool 37 @ivar address: the address 38 @type address: string 39 @ivar prefix: the prefix length 40 @type prefix: int 41 """ 42 43 __slots__ = ['family', 'negation', 'address', 'prefix'] 44
45 - def __init__(self, family, negation, address, prefix):
46 self.family = family 47 self.negation = negation 48 self.address = address 49 self.prefix = prefix
50
51 - def __str__(self):
52 if self.negation: 53 return "!%d:%s/%s" % (self.family, self.address, self.prefix) 54 else: 55 return "%d:%s/%s" % (self.family, self.address, self.prefix)
56
57 - def to_wire(self, file):
58 if self.family == 1: 59 address = dns.inet.inet_pton(dns.inet.AF_INET, self.address) 60 elif self.family == 2: 61 address = dns.inet.inet_pton(dns.inet.AF_INET6, self.address) 62 else: 63 address = binascii.unhexlify(self.address) 64 # 65 # Truncate least significant zero bytes. 66 # 67 last = 0 68 for i in xrange(len(address) - 1, -1, -1): 69 if address[i] != maybe_chr(0): 70 last = i + 1 71 break 72 address = address[0: last] 73 l = len(address) 74 assert l < 128 75 if self.negation: 76 l |= 0x80 77 header = struct.pack('!HBB', self.family, self.prefix, l) 78 file.write(header) 79 file.write(address)
80
81 82 -class APL(dns.rdata.Rdata):
83 84 """APL record. 85 86 @ivar items: a list of APL items 87 @type items: list of APL_Item 88 @see: RFC 3123""" 89 90 __slots__ = ['items'] 91
92 - def __init__(self, rdclass, rdtype, items):
93 super(APL, self).__init__(rdclass, rdtype) 94 self.items = items
95
96 - def to_text(self, origin=None, relativize=True, **kw):
97 return ' '.join(map(str, self.items))
98 99 @classmethod
100 - def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
101 items = [] 102 while 1: 103 token = tok.get().unescape() 104 if token.is_eol_or_eof(): 105 break 106 item = token.value 107 if item[0] == '!': 108 negation = True 109 item = item[1:] 110 else: 111 negation = False 112 (family, rest) = item.split(':', 1) 113 family = int(family) 114 (address, prefix) = rest.split('/', 1) 115 prefix = int(prefix) 116 item = APLItem(family, negation, address, prefix) 117 items.append(item) 118 119 return cls(rdclass, rdtype, items)
120
121 - def to_wire(self, file, compress=None, origin=None):
122 for item in self.items: 123 item.to_wire(file)
124 125 @classmethod
126 - def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
127 128 items = [] 129 while 1: 130 if rdlen == 0: 131 break 132 if rdlen < 4: 133 raise dns.exception.FormError 134 header = struct.unpack('!HBB', wire[current: current + 4]) 135 afdlen = header[2] 136 if afdlen > 127: 137 negation = True 138 afdlen -= 128 139 else: 140 negation = False 141 current += 4 142 rdlen -= 4 143 if rdlen < afdlen: 144 raise dns.exception.FormError 145 address = wire[current: current + afdlen].unwrap() 146 l = len(address) 147 if header[0] == 1: 148 if l < 4: 149 address += b'\x00' * (4 - l) 150 address = dns.inet.inet_ntop(dns.inet.AF_INET, address) 151 elif header[0] == 2: 152 if l < 16: 153 address += b'\x00' * (16 - l) 154 address = dns.inet.inet_ntop(dns.inet.AF_INET6, address) 155 else: 156 # 157 # This isn't really right according to the RFC, but it 158 # seems better than throwing an exception 159 # 160 address = codecs.encode(address, 'hex_codec') 161 current += afdlen 162 rdlen -= afdlen 163 item = APLItem(header[0], negation, address, header[1]) 164 items.append(item) 165 return cls(rdclass, rdtype, items)
166