Skip to content

Commit

Permalink
libnetplan: expose DNS configuration from netdefs
Browse files Browse the repository at this point in the history
Add iterators for nameservers and search domains.
  • Loading branch information
daniloegea authored and slyon committed Aug 16, 2023
1 parent b0f60d3 commit 70bff51
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 0 deletions.
7 changes: 7 additions & 0 deletions python-cffi/netplan/_build_cffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
char* label;
} NetplanAddressOptions;
struct address_iter { ...; };
struct nameserver_iter { ...; };
// Error handling
uint64_t netplan_error_code(NetplanError* error);
Expand Down Expand Up @@ -105,6 +106,12 @@
struct address_iter* _netplan_netdef_new_address_iter(NetplanNetDefinition* netdef);
NetplanAddressOptions* _netplan_address_iter_next(struct address_iter* it);
void _netplan_address_iter_free(struct address_iter* it);
struct nameserver_iter* _netplan_netdef_new_nameserver_iter(NetplanNetDefinition* netdef);
char* _netplan_nameserver_iter_next(struct nameserver_iter* it);
void _netplan_nameserver_iter_free(struct nameserver_iter* it);
struct nameserver_iter* _netplan_netdef_new_search_domain_iter(NetplanNetDefinition* netdef);
char* _netplan_search_domain_iter_next(struct nameserver_iter* it);
void _netplan_search_domain_iter_free(struct nameserver_iter* it);
// Utils
gboolean netplan_util_dump_yaml_subtree(const char* prefix, int input_fd, int output_fd, NetplanError** error);
Expand Down
45 changes: 45 additions & 0 deletions python-cffi/netplan/netdef.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ def dhcp4(self) -> bool:
def dhcp6(self) -> bool:
return bool(lib.netplan_netdef_get_dhcp6(self._ptr))

@property
def nameserver_addresses(self) -> '_NetdefNameserverIterator':
return _NetdefNameserverIterator(self._ptr)

@property
def nameserver_search(self) -> '_NetdefSearchDomainIterator':
return _NetdefSearchDomainIterator(self._ptr)

@property
def macaddress(self) -> str:
return _string_realloc_call_no_error(lambda b: lib.netplan_netdef_get_macaddress(self._ptr, b, len(b)))

Expand Down Expand Up @@ -189,3 +198,39 @@ def __next__(self):
lifetime = ffi.string(content.lifetime).decode('utf-8') if content.lifetime else None
label = ffi.string(content.label).decode('utf-8') if content.label else None
return NetplanAddress(address, lifetime, label)


class _NetdefNameserverIterator:
def __init__(self, netdef: NetDefinition):
self.netdef = netdef
self.iterator = lib._netplan_netdef_new_nameserver_iter(netdef)

def __del__(self):
lib._netplan_nameserver_iter_free(self.iterator)

def __iter__(self):
return self

def __next__(self):
next_value = lib._netplan_nameserver_iter_next(self.iterator)
if not next_value:
raise StopIteration
return ffi.string(next_value).decode('utf-8')


class _NetdefSearchDomainIterator:
def __init__(self, netdef):
self.netdef = netdef
self.iterator = lib._netplan_netdef_new_search_domain_iter(netdef)

def __del__(self):
lib._netplan_search_domain_iter_free(self.iterator)

def __iter__(self):
return self

def __next__(self):
next_value = lib._netplan_search_domain_iter_next(self.iterator)
if not next_value:
raise StopIteration
return ffi.string(next_value).decode('utf-8')
7 changes: 7 additions & 0 deletions src/types-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ struct address_iter {
NetplanAddressOptions* last_address;
};

struct nameserver_iter {
guint ip4_index;
guint ip6_index;
guint search_index;
NetplanNetDefinition* netdef;
};

typedef struct {
NetplanWifiMode mode;
char* ssid;
Expand Down
18 changes: 18 additions & 0 deletions src/util-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,24 @@ _netplan_address_iter_next(struct address_iter* it);
NETPLAN_INTERNAL void
_netplan_address_iter_free(struct address_iter* it);

NETPLAN_INTERNAL struct nameserver_iter*
_netplan_netdef_new_nameserver_iter(NetplanNetDefinition* netdef);

NETPLAN_INTERNAL char*
_netplan_nameserver_iter_next(struct nameserver_iter* it);

NETPLAN_INTERNAL void
_netplan_nameserver_iter_free(struct nameserver_iter* it);

NETPLAN_INTERNAL struct nameserver_iter*
_netplan_netdef_new_search_domain_iter(NetplanNetDefinition* netdef);

NETPLAN_INTERNAL char*
_netplan_search_domain_iter_next(struct nameserver_iter* it);

NETPLAN_INTERNAL void
_netplan_search_domain_iter_free(struct nameserver_iter* it);

NETPLAN_INTERNAL struct netdef_pertype_iter*
_netplan_state_new_netdef_pertype_iter(NetplanState* np_state, const char* def_type);

Expand Down
57 changes: 57 additions & 0 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,63 @@ _netplan_address_iter_free(struct address_iter* it)
g_free(it);
}

struct nameserver_iter*
_netplan_netdef_new_nameserver_iter(NetplanNetDefinition* netdef)
{
struct nameserver_iter* it = g_malloc0(sizeof(struct nameserver_iter));
it->ip4_index = 0;
it->ip6_index = 0;
it->netdef = netdef;

return it;
}

char*
_netplan_nameserver_iter_next(struct nameserver_iter* it)
{
if (it->netdef->ip4_nameservers && it->ip4_index < it->netdef->ip4_nameservers->len) {
return g_array_index(it->netdef->ip4_nameservers, char*, it->ip4_index++);
}

if (it->netdef->ip6_nameservers && it->ip6_index < it->netdef->ip6_nameservers->len) {
return g_array_index(it->netdef->ip6_nameservers, char*, it->ip6_index++);
}

return NULL;
}

void
_netplan_nameserver_iter_free(struct nameserver_iter* it)
{
g_free(it);
}

struct nameserver_iter*
_netplan_netdef_new_search_domain_iter(NetplanNetDefinition* netdef)
{
struct nameserver_iter* it = g_malloc0(sizeof(struct nameserver_iter));
it->search_index = 0;
it->netdef = netdef;

return it;
}

char*
_netplan_search_domain_iter_next(struct nameserver_iter* it)
{
if (it->netdef->search_domains && it->search_index < it->netdef->search_domains->len) {
return g_array_index(it->netdef->search_domains, char*, it->search_index++);
}

return NULL;
}

void
_netplan_search_domain_iter_free(struct nameserver_iter* it)
{
g_free(it);
}

struct netdef_pertype_iter {
NetplanDefType type;
GHashTableIter iter;
Expand Down
31 changes: 31 additions & 0 deletions tests/test_libnetplan.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,37 @@ def test_drop_iterator_before_finishing(self):
del iter


class TestNetdefNameserverSearchDomainIterator(TestBase):
def test_with_empty_nameservers(self):
state = state_from_yaml(self.confdir, '''network:
ethernets:
eth0: {}''')

netdef = next(netplan.netdef.NetDefinitionIterator(state, "ethernets"))
self.assertSetEqual(set(), set(ip for ip in netdef.nameserver_addresses))
self.assertSetEqual(set(), set(ip for ip in netdef.nameserver_search))

def test_iter_ethernets_nameservers_and_domains(self):
state = state_from_yaml(self.confdir, '''network:
ethernets:
eth0:
nameservers:
search:
- home.local
- mynet.local
addresses:
- 192.168.0.1
- 172.16.0.1
- 1234:4321:abcd::cdef
- abcd::1234''')

expected_addresses = set(["1234:4321:abcd::cdef", "abcd::1234", "192.168.0.1", "172.16.0.1"])
expected_domains = set(["home.local", "mynet.local"])
netdef = next(netplan.netdef.NetDefinitionIterator(state, "ethernets"))
self.assertSetEqual(expected_addresses, set(ip for ip in netdef.nameserver_addresses))
self.assertSetEqual(expected_domains, set(domain for domain in netdef.nameserver_search))


class TestParser(TestBase):
def test_load_yaml_from_fd_empty(self):
parser = netplan.Parser()
Expand Down

0 comments on commit 70bff51

Please sign in to comment.