Commit 2b9338ea authored by Michael Tremer's avatar Michael Tremer

network: Export family, first_address and last_address in Python

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: default avatarMichael Tremer <michael.tremer@ipfire.org>
parent b43edb61
......@@ -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;
......
......@@ -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);
......
......@@ -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)
......
......@@ -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)
......
......@@ -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 },
};
......
......@@ -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) {
......
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