123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- #!/usr/bin/env python3
- # usage: generate-ip-mappings.py
- # 2 files ipv4.csv and ipv6.csv will be generated
- # in sqlite3 terminal:
- #
- # .mode csv
- # .import 'full path to ipv4.csv' ip_mapping
- # .import 'full path to ipv6.csv' ipv6_mapping
- #
- # For query by ip:
- # SELECT * FROM ip_mapping WHERE `ip_start` <= ip-in-decimal AND `ip_end` >= ip-in-decimal ORDER BY `ip_start` DESC LIMIT 1;
- # SELECT * FROM ipv6_mapping WHERE `ip_start` <= upperIPv6("ipv6_addr") AND `ip_end` >= upperIPv6("ipv6_addr") ORDER BY `ip_start` DESC LIMIT 1;
- import socket
- import struct
- import csv
- import os
- import sys
- # import zipfile
- # import urllib.request
- def ip2int(addr):
- return struct.unpack("!I", socket.inet_aton(addr))[0]
- # Keep only the upper 64bit, as we only need that for geolocation
- def ipv62int64(addr):
- hi, lo = struct.unpack('!QQ', socket.inet_pton(socket.AF_INET6, addr))
- return hi
- CSV_WEB_LINK = 'https://download.db-ip.com/free/dbip-city-lite-2025-01.csv.gz'
- CSV_FILE = 'dbip-city-lite-2025-01.csv'
- if not os.path.exists(CSV_FILE):
- print("File = {} does not exist. Download it from = {} ".format(CSV_FILE, CSV_WEB_LINK))
- sys.exit(1)
- # Format: 1.0.0.0,1.0.0.255,OC,AU,Queensland,"South Brisbane",-27.4748,153.017
- with open(CSV_FILE, 'r') as csvfile, open('ipv4.csv', 'w') as ipv4, open('ipv6.csv', 'w') as ipv6:
- iplist = csv.reader(csvfile, delimiter=',', quotechar='"')
- for row in iplist:
- # Skip reserved range
- if row[3] == "ZZ":
- continue
- # Skip empty latitude and longitude
- if row[6] == "" or row[7] == "":
- continue
- if row[0].find(':') == -1:
- ipv4_line = True
- else:
- ipv4_line = False
- if ipv4_line:
- ip_start = ip2int(row[0])
- ip_end = ip2int(row[1])
- else:
- ip_start = ipv62int64(row[0])
- ip_end = ipv62int64(row[1])
- # Some IPv6 entries are duplicated after removing the lower 64bit
- if ip_start == ip_end:
- continue
- # Sqlite doesn't support unsigned int 64
- _int64_max = pow(2, 63) - 1
- if ip_start > _int64_max or ip_end > _int64_max:
- continue
- latitude = float(row[6])
- longitude = float(row[7])
- country = row[3]
- if ipv4_line:
- print('%d,%d,%f,%f,%s' % (ip_start, ip_end, latitude, longitude, country), file = ipv4)
- else:
- print('%d,%d,%f,%f,%s' % (ip_start, ip_end, latitude, longitude, country), file = ipv6)
|