RPKI Engine 1.0
|
00001 """ 00002 Classes to represent IP addresses. 00003 00004 Given some of the other operations we need to perform on them, it's 00005 most convenient to represent IP addresses as Python "long" values. 00006 The classes in this module just wrap suitable read/write syntax around 00007 the underlying "long" type. 00008 00009 These classes also supply a "bits" attribute for use by other code 00010 built on these classes; for the most part, IPv6 addresses really are 00011 just IPv4 addresses with more bits, so we supply the number of bits 00012 once, here, thus avoiding a lot of duplicate code elsewhere. 00013 00014 $Id: ipaddrs.py 3551 2010-11-14 23:28:45Z sra $ 00015 00016 Copyright (C) 2009 Internet Systems Consortium ("ISC") 00017 00018 Permission to use, copy, modify, and distribute this software for any 00019 purpose with or without fee is hereby granted, provided that the above 00020 copyright notice and this permission notice appear in all copies. 00021 00022 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 00023 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00024 AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 00025 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 00026 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 00027 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00028 PERFORMANCE OF THIS SOFTWARE. 00029 00030 Portions copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN") 00031 00032 Permission to use, copy, modify, and distribute this software for any 00033 purpose with or without fee is hereby granted, provided that the above 00034 copyright notice and this permission notice appear in all copies. 00035 00036 THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH 00037 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00038 AND FITNESS. IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT, 00039 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 00040 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 00041 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00042 PERFORMANCE OF THIS SOFTWARE. 00043 """ 00044 00045 import socket, struct 00046 00047 class v4addr(long): 00048 """ 00049 IPv4 address. 00050 00051 Derived from long, but supports IPv4 print syntax. 00052 """ 00053 00054 bits = 32 00055 00056 def __new__(cls, x): 00057 """ 00058 Construct a v4addr object. 00059 """ 00060 if isinstance(x, str): 00061 return cls.from_bytes(socket.inet_pton(socket.AF_INET, ".".join(str(int(i)) for i in x.split(".")))) 00062 else: 00063 return long.__new__(cls, x) 00064 00065 def to_bytes(self): 00066 """ 00067 Convert a v4addr object to a raw byte string. 00068 """ 00069 return struct.pack("!I", long(self)) 00070 00071 @classmethod 00072 def from_bytes(cls, x): 00073 """ 00074 Convert from a raw byte string to a v4addr object. 00075 """ 00076 return cls(struct.unpack("!I", x)[0]) 00077 00078 def __str__(self): 00079 """ 00080 Convert a v4addr object to string format. 00081 """ 00082 return socket.inet_ntop(socket.AF_INET, self.to_bytes()) 00083 00084 class v6addr(long): 00085 """ 00086 IPv6 address. 00087 00088 Derived from long, but supports IPv6 print syntax. 00089 """ 00090 00091 bits = 128 00092 00093 def __new__(cls, x): 00094 """ 00095 Construct a v6addr object. 00096 """ 00097 if isinstance(x, str): 00098 return cls.from_bytes(socket.inet_pton(socket.AF_INET6, x)) 00099 else: 00100 return long.__new__(cls, x) 00101 00102 def to_bytes(self): 00103 """ 00104 Convert a v6addr object to a raw byte string. 00105 """ 00106 return struct.pack("!QQ", long(self) >> 64, long(self) & 0xFFFFFFFFFFFFFFFF) 00107 00108 @classmethod 00109 def from_bytes(cls, x): 00110 """ 00111 Convert from a raw byte string to a v6addr object. 00112 """ 00113 x = struct.unpack("!QQ", x) 00114 return cls((x[0] << 64) | x[1]) 00115 00116 def __str__(self): 00117 """ 00118 Convert a v6addr object to string format. 00119 """ 00120 return socket.inet_ntop(socket.AF_INET6, self.to_bytes()) 00121 00122 def parse(s): 00123 """ 00124 Parse a string as either an IPv4 or IPv6 address, and return object of appropriate class. 00125 """ 00126 if isinstance(s, unicode): 00127 s = s.encode("ascii") 00128 return v6addr(s) if ":" in s else v4addr(s)