loc_network_get_asn;
loc_network_get_country_code;
loc_network_has_flag;
+ loc_network_is_subnet_of;
loc_network_match_asn;
loc_network_match_country_code;
loc_network_match_flag;
int loc_network_set_flag(struct loc_network* network, uint32_t flag);
int loc_network_match_flag(struct loc_network* network, uint32_t flag);
+int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other);
+
#ifdef LIBLOC_PRIVATE
int loc_network_to_database_v1(struct loc_network* network, struct loc_database_network_v1* dbobj);
return loc_network_has_flag(network, flag);
}
+LOC_EXPORT int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other) {
+ // If the start address of the other network is smaller than this network,
+ // it cannot be a subnet.
+ if (in6_addr_cmp(&self->start_address, &other->start_address) < 0)
+ return 0;
+
+ // Get the end addresses
+ struct in6_addr last_address_self = make_last_address(&self->start_address, self->prefix);
+ struct in6_addr last_address_other = make_last_address(&other->start_address, other->prefix);
+
+ // If the end address of the other network is greater than this network,
+ // it cannot be a subnet.
+ if (in6_addr_cmp(&last_address_self, &last_address_other) > 0)
+ return 0;
+
+ return 1;
+}
+
LOC_EXPORT int loc_network_to_database_v1(struct loc_network* network, struct loc_database_network_v1* dbobj) {
// Add country code
loc_country_code_copy(dbobj->country_code, network->country_code);
suffix = "networks"
mode = "w"
- def __init__(self, f, prefix=None):
- self.f, self.prefix = f, prefix
+ def __init__(self, f, prefix=None, flatten=True):
+ self.f, self.prefix, self.flatten = f, prefix, flatten
+
+ # The previously written network
+ self._last_network = None
# Immediately write the header
self._write_header()
def __repr__(self):
return "<%s f=%s>" % (self.__class__.__name__, self.f)
+ def _flatten(self, network):
+ """
+ Checks if the given network needs to be written to file,
+ or if it is a subnet of the previously written network.
+ """
+ if self._last_network and network.is_subnet_of(self._last_network):
+ return True
+
+ # Remember this network for the next call
+ self._last_network = network
+ return False
+
def _write_header(self):
"""
The header of the file
"""
pass
- def write(self, network):
+ def _write_network(self, network):
self.f.write("%s\n" % network)
+ def write(self, network):
+ if self.flatten and self._flatten(network):
+ log.debug("Skipping writing network %s" % network)
+ return
+
+ # Write the network to file
+ self._write_network(network)
+
def finish(self):
"""
Called when all data has been written
def _write_header(self):
self.f.write("create %s hash:net family inet hashsize 1024 maxelem 65536\n" % self.prefix)
- def write(self, network):
+ def _write_network(self, network):
self.f.write("add %s %s\n" % (self.prefix, network))
def _write_footer(self):
self.f.write("}\n")
- def write(self, network):
+ def _write_network(self, network):
self.f.write(" %s,\n" % network)
suffix = "iv"
mode = "wb"
- def write(self, network):
+ def _write_network(self, network):
n = ipaddress.ip_network("%s" % network)
for address in (n.network_address, n.broadcast_address):
Py_RETURN_NONE;
}
+static PyObject* Network_is_subnet_of(NetworkObject* self, PyObject* args) {
+ NetworkObject* other = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!", &NetworkType, &other))
+ return NULL;
+
+ if (loc_network_is_subnet_of(self->network, other->network))
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
static struct PyMethodDef Network_methods[] = {
{
"has_flag",
METH_VARARGS,
NULL,
},
+ {
+ "is_subnet_of",
+ (PyCFunction)Network_is_subnet_of,
+ METH_VARARGS,
+ NULL,
+ },
{
"set_flag",
(PyCFunction)Network_set_flag,
size_t nodes = loc_network_tree_count_nodes(tree);
printf("The tree has %zu nodes\n", nodes);
+ // Check subnet function
+ err = loc_network_is_subnet_of(network1, network2);
+ if (err != 0) {
+ fprintf(stderr, "Subnet check 1 failed: %d\n", err);
+ exit(EXIT_FAILURE);
+ }
+
+ err = loc_network_is_subnet_of(network2, network1);
+ if (err != 1) {
+ fprintf(stderr, "Subnet check 2 failed: %d\n", err);
+ exit(EXIT_FAILURE);
+ }
+
// Create a database
struct loc_writer* writer;
err = loc_writer_new(ctx, &writer, NULL, NULL);