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 2424 2009-05-11 06:37:32Z 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 """Convert a v4addr object to a raw byte string.""" 00067 return struct.pack("!I", long(self)) 00068 00069 @classmethod 00070 def from_bytes(cls, x): 00071 """Convert from a raw byte string to a v4addr object.""" 00072 return cls(struct.unpack("!I", x)[0]) 00073 00074 def __str__(self): 00075 """Convert a v4addr object to string format.""" 00076 return socket.inet_ntop(socket.AF_INET, self.to_bytes()) 00077 00078 class v6addr(long): 00079 """ 00080 IPv6 address. 00081 00082 Derived from long, but supports IPv6 print syntax. 00083 """ 00084 00085 bits = 128 00086 00087 def __new__(cls, x): 00088 """Construct a v6addr object.""" 00089 if isinstance(x, str): 00090 return cls.from_bytes(socket.inet_pton(socket.AF_INET6, x)) 00091 else: 00092 return long.__new__(cls, x) 00093 00094 def to_bytes(self): 00095 """Convert a v6addr object to a raw byte string.""" 00096 return struct.pack("!QQ", long(self) >> 64, long(self) & 0xFFFFFFFFFFFFFFFF) 00097 00098 @classmethod 00099 def from_bytes(cls, x): 00100 """Convert from a raw byte string to a v6addr object.""" 00101 x = struct.unpack("!QQ", x) 00102 return cls((x[0] << 64) | x[1]) 00103 00104 def __str__(self): 00105 """Convert a v6addr object to string format.""" 00106 return socket.inet_ntop(socket.AF_INET6, self.to_bytes())