Name

python-location - Python module to query the IPFire Location Database

Synopsis

import location

db = location.open()

network = db.lookup("81.3.27.38")

Description

The location module makes libloc available in Python. It can look up addresses, list networks, Autonomous Systems and countries, verify databases, and write new ones.

It is the module that location(1) and location-importer(1) are written with. Its classes are written in C, and call libloc directly (see libloc(3)).

All functions that look something up return None if there is nothing. Invalid arguments raise ValueError or TypeError, and anything else that goes wrong in the library raises OSError with the error number that the library has returned.

Importing the module adds two handlers to the location logger of the logging module: one that writes to the console, and one that writes to syslog.

Functions and Constants

location.open(path=None)

Opens the database at path, or the database of the system if path is omitted, and returns a Database.

location.country_code_is_valid(code)

Returns whether code is a valid country code, which has two upper case letters, and does not start with an X (see loc_country_code_is_valid(3)).

location.discover_latest_version(version=DATABASE_VERSION_LATEST)

Asks the DNS when the latest database was published, and returns the time as seconds since the epoch, or None if that could not be found out (see loc_discover_latest_version(3)). Other threads can run while it is waiting for the answer.

location.set_log_level(priority)

Sets the priority of the messages that the library logs, as a syslog(3) priority, for example 7 for LOG_DEBUG.

location.DATABASE_PATH

The path of the database of the system, usually /var/lib/location/database.db.

location.DATABASE_VERSION_LATEST

The latest version of the database format.

location.NETWORK_FLAG_ANONYMOUS_PROXY, location.NETWORK_FLAG_SATELLITE_PROVIDER, location.NETWORK_FLAG_ANYCAST, location.NETWORK_FLAG_DROP

The flags that a network can have.

location.__version__

The version of libloc.

Database

location.Database(path)

Opens the database at path. The database is mapped into memory, and is read again automatically when its file has been replaced, so that it only needs to be opened once. If it cannot be opened, OSError is raised.

lookup(address)

Returns the Network that address is in, or None if the database knows nothing about it. address is a string, for example "81.3.27.38" or "2001:db8::1". Invalid addresses raise ValueError.

get_as(number)

Returns the AS with that number, or None.

get_country(code)

Returns the Country with that code, or None. Invalid codes raise ValueError.

search_networks(country_codes=None, asns=None, flags=0, family=0, flatten=False)

Returns an iterator over all networks that are in one of the countries in the list country_codes, or belong to one of the AS numbers in the list asns, or have one of the flags, or over all networks if none of them are given. family can be socket.AF_INET or socket.AF_INET6 to only return networks of that family. If flatten is true, networks that are inside other networks are being taken out of those, so that no two networks that are being returned overlap.

search_as(string)

Returns an iterator over all Autonomous Systems whose names contain string, ignoring case.

list_bogons(family=0)

Returns an iterator over all networks that should not be seen on the Internet, because they are reserved, or have not been allocated to anybody.

ases, countries, networks

Iterators over all Autonomous Systems, countries, and networks.

networks_flattened

An iterator over all networks, of which none overlap.

verify(key)

Returns whether the database has been signed with the public key, which is an open file. This is False when there is no signature or when key is not a key. Verifying reads the entire database, and other threads can run in the meantime.

reload()

Reads the database again if its file has been replaced, and returns whether it has. This happens automatically every once in a while (see loc_database_reload(3)).

created_at, vendor, description, license

When the database was created, as seconds since the epoch, and who has created it, what it is, and under which license it has been published.

A Database can be used by any number of threads at the same time.

Network

location.Network(network)

Creates a network from a string, for example "10.0.0.0/8". Invalid networks raise ValueError.

country_code, asn

The country code and the AS number of the network, or None. Both can be changed.

family

socket.AF_INET or socket.AF_INET6.

first_address, last_address

The first and last address of the network as strings.

has_flag(flag), set_flag(flag)

Return whether the network has flag, and give it flag.

is_subnet_of(other)

Returns whether the network is inside the network other.

subnets

A tuple with the two halves of the network. Networks that only have one address raise ValueError.

exclude(other)

Returns a list of the networks that are left of the network after other has been taken out of it.

reverse_pointer(suffix=None)

Returns the name of the network in the DNS, which ends in suffix, or in in-addr.arpa. or ip6.arpa. if suffix is omitted, for example "*.10.in-addr.arpa.", or None if the prefix of the network is not a multiple of 8 for IPv4, or of 4 for IPv6.

Networks can be compared with == and sorted. str() returns the network as a string.

AS

location.AS(number)

Creates an Autonomous System.

number

The AS number.

name

The name of the Autonomous System, or None. It can be changed.

ASes can be compared, sorted, and used in sets and as keys in dictionaries. str() returns for example "AS204867 - Lightning Wire Labs GmbH".

Country

location.Country(code)

Creates a country. Invalid codes raise ValueError.

code

The country code.

name, continent_code

The name of the country, and the code of its continent, or None. Both can be changed.

Countries can be compared, sorted, and used in sets and as keys in dictionaries. str() returns the code.

Writer

location.Writer(private_key1=None, private_key2=None)

Creates a new database, which is signed with up to two private keys, which are open files (see loc_writer_new(3)).

vendor, description, license

Who has created the database, what it is, and under which license it is published.

add_network(network)

Adds a network, and returns it as a Network, whose country code, AS number and flags can then be set. If the network has already been added, IndexError is raised.

add_as(number)

Adds an Autonomous System, and returns it as an AS, whose name can then be set.

add_country(code)

Adds a country, and returns it as a Country, whose name and continent can then be set.

write(path, version=DATABASE_VERSION_LATEST)

Writes the database to path. Other threads can run while the database is being written. Until it has been written, the writer cannot be changed, and anything that tries raises RuntimeError. The networks, Autonomous Systems and countries that have been added to it must not be changed either.

Other Modules

location.export

Exports networks for ipset, nftables, and xt_geoip, which is what location export uses (see location(1)). Exporter(db, writer) takes one of the writers in location.export.formats, and its export(directory, families, countries, asns) writes one file for every country and AS number and family into directory.

location.downloader

Downloads new databases, which is what location update uses. Downloader().download(public_key, timestamp=None) downloads a database that is newer than timestamp from one of the mirrors, and verifies it with the public key in the file public_key. It returns a temporary file, whose name is in name.

Examples

Look up an address:

import location

db = location.open()

network = db.lookup("81.3.27.38")
if network:
        print(network, network.country_code, network.asn)

Print all networks in Germany that are not inside each other:

import socket

for network in db.search_networks(country_codes=["DE"],
                family=socket.AF_INET, flatten=True):
        print(network)

Find out who an AS number belongs to:

print(db.get_as(204867))

Verify a database:

with open("/var/lib/location/signing-key.pem") as f:
        if not db.verify(f):
                raise RuntimeError("The database has not been signed by the vendor")

Write a new database:

writer = location.Writer()
writer.vendor = "Example"

network = writer.add_network("192.0.2.0/24")
network.country_code = "DE"
network.asn = 64512

writer.write("example.db")

See Also

Authors

Michael Tremer