Commit 8c2bcab8 by William Tisäter

Initial commit for IPv6 support

parent 2bd928e6
...@@ -176,7 +176,6 @@ class GeoIP(GeoIPBase): ...@@ -176,7 +176,6 @@ class GeoIP(GeoIPBase):
""" """
ipnum = ip2long(addr) ipnum = ip2long(addr)
if not ipnum: if not ipnum:
raise ValueError("Invalid IP address: %s" % addr) raise ValueError("Invalid IP address: %s" % addr)
...@@ -196,10 +195,11 @@ class GeoIP(GeoIPBase): ...@@ -196,10 +195,11 @@ class GeoIP(GeoIPBase):
@return: offset of start of record @return: offset of start of record
@rtype: int @rtype: int
""" """
offset = 0
for depth in range(31, -1, -1): offset = 0
seek_depth = 127 if len(str(ipnum)) > 10 else 31
for depth in range(seek_depth, -1, -1):
if self._flags & const.MEMORY_CACHE: if self._flags & const.MEMORY_CACHE:
startIndex = 2 * self._recordLength * offset startIndex = 2 * self._recordLength * offset
length = 2 * self._recordLength length = 2 * self._recordLength
...@@ -214,22 +214,15 @@ class GeoIP(GeoIPBase): ...@@ -214,22 +214,15 @@ class GeoIP(GeoIPBase):
for i in range(2): for i in range(2):
for j in range(self._recordLength): for j in range(self._recordLength):
x[i] += ord(buf[self._recordLength * i + j]) << (j * 8) x[i] += ord(buf[self._recordLength * i + j]) << (j * 8)
if ipnum & (1 << depth): if ipnum & (1 << depth):
if x[1] >= self._databaseSegments: if x[1] >= self._databaseSegments:
return x[1] return x[1]
offset = x[1] offset = x[1]
else: else:
if x[0] >= self._databaseSegments: if x[0] >= self._databaseSegments:
return x[0] return x[0]
offset = x[0] offset = x[0]
raise Exception('Error traversing database - perhaps it is corrupt?') raise Exception('Error traversing database - perhaps it is corrupt?')
def _get_org(self, ipnum): def _get_org(self, ipnum):
...@@ -436,7 +429,6 @@ class GeoIP(GeoIPBase): ...@@ -436,7 +429,6 @@ class GeoIP(GeoIPBase):
else: else:
raise GeoIPError('Invalid database type; country_* methods expect '\ raise GeoIPError('Invalid database type; country_* methods expect '\
'Country, City, or Region database') 'Country, City, or Region database')
except ValueError: except ValueError:
raise GeoIPError('*_by_addr methods only accept IP addresses. Use *_by_name for hostnames. (Address: %s)' % addr) raise GeoIPError('*_by_addr methods only accept IP addresses. Use *_by_name for hostnames. (Address: %s)' % addr)
......
""" """
Misc. utility functions. It is part of the pygeoip package. Misc. utility functions. It is part of the pygeoip package.
@author: Jennifer Ennis <zaylea at gmail dot com> @author: Jennifer Ennis <zaylea at gmail dot com>
@license: @license:
Copyright(C) 2004 MaxMind LLC Copyright(C) 2004 MaxMind LLC
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/lgpl.txt>. along with this program. If not, see <http://www.gnu.org/licenses/lgpl.txt>.
""" """
import six import six
import struct
def ip2long(ip): import socket
""" from array import array
Convert a IPv4 address into a 32-bit integer.
@param ip: quad-dotted IPv4 address def ip2long(ip):
@type ip: str """
@return: network byte order 32-bit integer Wrapper function for IPv4 and IPv6 converters
@rtype: int @param ip: IPv4 or IPv6 address
""" @type ip: str
ip_array = ip.split('.') """
if ip.find(':') >= 0:
if six.PY3: return ip2long_v6(ip)
# int and long are unified in py3 else:
ip_long = int(ip_array[0]) * 16777216 + int(ip_array[1]) * 65536 + int(ip_array[2]) * 256 + int(ip_array[3]) return ip2long_v4(ip)
else:
ip_long = long(ip_array[0]) * 16777216 + long(ip_array[1]) * 65536 + long(ip_array[2]) * 256 + long(ip_array[3])
return ip_long def ip2long_v4(ip):
"""
Convert a IPv4 address into a 32-bit integer.
@param ip: quad-dotted IPv4 address
@type ip: str
@return: network byte order 32-bit integer
@rtype: int
"""
ip_array = ip.split('.')
if six.PY3:
# int and long are unified in py3
ip_long = int(ip_array[0]) * 16777216 + int(ip_array[1]) * 65536 + int(ip_array[2]) * 256 + int(ip_array[3])
else:
ip_long = long(ip_array[0]) * 16777216 + long(ip_array[1]) * 65536 + long(ip_array[2]) * 256 + long(ip_array[3])
return ip_long
def ip2long_v6(ip):
"""
Convert a IPv6 address into long.
@param ip: IPv6 address
@type ip: str
@return: network byte order long
@rtype: long
"""
ipbyte = socket.inet_pton(socket.AF_INET6, ip)
ipnum = array('L', struct.unpack('!4L', ipbyte))
ipnum.reverse()
return sum(ipnum[i] << (i * 32) for i in range(len(ipnum)))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment