]> git.ipfire.org Git - location/libloc.git/commitdiff
network: Export family, first_address and last_address in Python
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 18 Sep 2020 13:46:58 +0000 (13:46 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 18 Sep 2020 13:46:58 +0000 (13:46 +0000)
We can use this to avoid formatting the network in a string
representation which is then parsed again later to determine
the first and last addresses.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libloc.sym
src/loc/network.h
src/network.c
src/python/export.py
src/python/network.c
src/test-network.c

index 222a4cf7ef6b9e0008b18ad74af2ec1d0a0db3a7..b8296eb83cd5511b04587d492ee8cd49699af832 100644 (file)
@@ -80,6 +80,8 @@ global:
 
        # Network
        loc_network_address_family;
+       loc_network_format_first_address;
+       loc_network_format_last_address;
        loc_network_get_asn;
        loc_network_get_country_code;
        loc_network_has_flag;
index 6bc498f9ab2a9844d4fb8a0e0077bbc197c98060..70c3803e586218529fac2cddac54509cc7c8dc39 100644 (file)
@@ -37,6 +37,9 @@ struct loc_network* loc_network_ref(struct loc_network* network);
 struct loc_network* loc_network_unref(struct loc_network* network);
 char* loc_network_str(struct loc_network* network);
 int loc_network_address_family(struct loc_network* network);
+
+char* loc_network_format_first_address(struct loc_network* network);
+char* loc_network_format_last_address(struct loc_network* network);
 int loc_network_match_address(struct loc_network* network, const struct in6_addr* address);
 
 const char* loc_network_get_country_code(struct loc_network* network);
index a4c7646e90fccd4d4ca3622209f2d9ae202299d7..dc976e90018ec0e164360199eba2df8e12a61890 100644 (file)
@@ -278,6 +278,47 @@ LOC_EXPORT int loc_network_address_family(struct loc_network* network) {
        return AF_INET6;
 }
 
+static char* loc_network_format_address(struct loc_network* network, const struct in6_addr* address) {
+       const size_t length = INET6_ADDRSTRLEN;
+
+       char* string = malloc(length);
+       if (!string)
+               return NULL;
+
+       int r = 0;
+
+       switch (loc_network_address_family(network)) {
+               case AF_INET6:
+                       r = format_ipv6_address(address, string, length);
+                       break;
+
+               case AF_INET:
+                       r = format_ipv4_address(address, string, length);
+                       break;
+
+               default:
+                       r = -1;
+                       break;
+       }
+
+       if (r) {
+               ERROR(network->ctx, "Could not format IP address to string: %s\n", strerror(errno));
+               free(string);
+
+               return NULL;
+       }
+
+       return string;
+}
+
+LOC_EXPORT char* loc_network_format_first_address(struct loc_network* network) {
+       return loc_network_format_address(network, &network->first_address);
+}
+
+LOC_EXPORT char* loc_network_format_last_address(struct loc_network* network) {
+       return loc_network_format_address(network, &network->last_address);
+}
+
 LOC_EXPORT int loc_network_match_address(struct loc_network* network, const struct in6_addr* address) {
        // Address must be larger than the start address
        if (in6_addr_cmp(&network->first_address, address) > 0)
index 180d462fcad0e7e075afdb2082ca51a61152bfca..d15c6f0dc75564cd81d8c3fa344bf4dccbb67f7a 100644 (file)
@@ -143,12 +143,10 @@ class XTGeoIPOutputWriter(OutputWriter):
        mode = "wb"
 
        def _write_network(self, network):
-               n = ipaddress.ip_network("%s" % network)
-
-               for address in (n.network_address, n.broadcast_address):
+               for address in (network.first_address, network.last_address):
+                       # Convert this into a string of bits
                        bytes = socket.inet_pton(
-                               socket.AF_INET6 if address.version == 6 else socket.AF_INET,
-                               "%s" % address,
+                               network.family, address,
                        )
 
                        self.f.write(bytes)
index 5fbb17d2d2cf79303319d6465d87bc55e63b5b69..5496d1ed965e91d8f75d15b43ea56f7300e4a6e2 100644 (file)
@@ -166,6 +166,30 @@ static PyObject* Network_is_subnet_of(NetworkObject* self, PyObject* args) {
        Py_RETURN_FALSE;
 }
 
+static PyObject* Network_get_family(NetworkObject* self) {
+       int family = loc_network_address_family(self->network);
+
+       return PyLong_FromLong(family);
+}
+
+static PyObject* Network_get_first_address(NetworkObject* self) {
+       char* address = loc_network_format_first_address(self->network);
+
+       PyObject* obj = PyUnicode_FromString(address);
+       free(address);
+
+       return obj;
+}
+
+static PyObject* Network_get_last_address(NetworkObject* self) {
+       char* address = loc_network_format_last_address(self->network);
+
+       PyObject* obj = PyUnicode_FromString(address);
+       free(address);
+
+       return obj;
+}
+
 static struct PyMethodDef Network_methods[] = {
        {
                "has_flag",
@@ -203,6 +227,27 @@ static struct PyGetSetDef Network_getsetters[] = {
                NULL,
                NULL,
        },
+       {
+               "family",
+               (getter)Network_get_family,
+               NULL,
+               NULL,
+               NULL,
+       },
+       {
+               "first_address",
+               (getter)Network_get_first_address,
+               NULL,
+               NULL,
+               NULL,
+       },
+       {
+               "last_address",
+               (getter)Network_get_last_address,
+               NULL,
+               NULL,
+               NULL,
+       },
        { NULL },
 };
 
index c49c3ef4038a23c56bb75d136d275ced3b40fbc9..d38f13dd74605bc6cbfd039ef98b09e054b2422b 100644 (file)
@@ -46,7 +46,7 @@ int main(int argc, char** argv) {
 
        // Create a network
        struct loc_network* network1;
-       err = loc_network_new_from_string(ctx, &network1, "2001:db8::/32");
+       err = loc_network_new_from_string(ctx, &network1, "2001:db8::1/32");
        if (err) {
                fprintf(stderr, "Could not create the network\n");
                exit(EXIT_FAILURE);
@@ -65,6 +65,29 @@ int main(int argc, char** argv) {
                exit(EXIT_FAILURE);
        }
 
+       // Check if the first and last addresses are correct
+       char* string = loc_network_format_first_address(network1);
+       if (!string) {
+               fprintf(stderr, "Did get NULL instead of a string for the first address\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (strcmp(string, "2001:db8::") != 0) {
+               fprintf(stderr, "Got an incorrect first address: %s\n", string);
+               exit(EXIT_FAILURE);
+       }
+
+       string = loc_network_format_last_address(network1);
+       if (!string) {
+               fprintf(stderr, "Did get NULL instead of a string for the last address\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (strcmp(string, "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff") != 0) {
+               fprintf(stderr, "Got an incorrect last address: %s\n", string);
+               exit(EXIT_FAILURE);
+       }
+
        struct loc_network* network2;
        err = loc_network_new_from_string(ctx, &network2, "2001:db8:ffff::/48");
        if (err) {