ell 0.33 test suite fails on big endian machines
by Natanael Copa
Hi!
On alpine linux edge on s390x:
ncopa-edge-s390x:~/aports/main/ell/src/ell-0.33$ cat test-suite.log
================================
ell 0.33: ./test-suite.log
================================
# TOTAL: 31
# PASS: 30
# SKIP: 0
# XFAIL: 0
# FAIL: 1
# XPASS: 0
# ERROR: 0
.. contents:: :depth: 2
FAIL: unit/test-dhcp6
=====================
TEST: option parsing
Assertion failed: dhcp6_message_compare(solicit_data_1, sizeof(solicit_data_1), client_packet, client_packet_len) (unit/test-dhcp6.c: test_obtain_lease: 238)
TEST: lease parsing
TEST: obtain lease - no rapid commit
Aborted
FAIL unit/test-dhcp6 (exit status: 134)
Samme seems to happen on mips64.
Test passes on all little endian architectures (x86, x86_64, ppc64le, armv7, aarch64)
-nc
4 months, 1 week
[PATCH v7 1/6] dhcp-server: process DISCOVER and send OFFER
by James Prestwood
Add handling of DISCOVER messages and ability to send offers.
---
ell/dhcp-server.c | 330 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 330 insertions(+)
diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index 6b7e483..1af7465 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -41,6 +41,9 @@
/* 8 hours */
#define DEFAULT_DHCP_LEASE_SEC (8*60*60)
+/* 5 minutes */
+#define OFFER_TIME (5*60)
+
struct l_dhcp_server {
bool started;
int ifindex;
@@ -82,8 +85,335 @@ struct l_dhcp_server {
l_util_debug(server->debug_handler, server->debug_data, \
"%s:%i " fmt, __func__, __LINE__, ## args)
+static bool is_expired_lease(struct l_dhcp_lease *lease)
+{
+ if (lease->lifetime < l_time_to_secs(l_time_now()))
+ return true;
+
+ return false;
+}
+
+static bool match_lease_mac(const void *data, const void *user_data)
+{
+ const struct l_dhcp_lease *lease = data;
+ const uint8_t *mac = user_data;
+
+ return !memcmp(lease->mac, mac, 6);
+}
+
+static struct l_dhcp_lease *find_lease_by_mac(struct l_dhcp_server *server,
+ const uint8_t *mac)
+{
+ return l_queue_find(server->lease_list, match_lease_mac, mac);
+}
+
+/* Clear the old lease and create the new one */
+static int get_lease(struct l_dhcp_server *server, uint32_t yiaddr,
+ const uint8_t *mac,
+ struct l_dhcp_lease **lease_out)
+{
+ struct l_dhcp_lease *lease;
+
+ if (yiaddr == 0)
+ return -ENXIO;
+
+ if (ntohl(yiaddr) < server->start_ip)
+ return -ENXIO;
+
+ if (ntohl(yiaddr) > server->end_ip)
+ return -ENXIO;
+
+ if (l_memeq(mac, ETH_ALEN, 0xff))
+ return -ENXIO;
+
+ if (l_memeqzero(mac, ETH_ALEN))
+ return -ENXIO;
+
+ lease = find_lease_by_mac(server, mac);
+
+ if (lease) {
+ l_queue_remove(server->lease_list, lease);
+
+ *lease_out = lease;
+
+ return 0;
+ }
+
+ *lease_out = l_new(struct l_dhcp_lease, 1);
+
+ return 0;
+}
+
+static int compare_lifetime(const void *a, const void *b, void *user_data)
+{
+ const struct l_dhcp_lease *lease1 = a;
+ const struct l_dhcp_lease *lease2 = b;
+
+ return lease2->lifetime - lease1->lifetime;
+}
+
+static struct l_dhcp_lease *add_lease(struct l_dhcp_server *server,
+ uint32_t expire, const uint8_t *chaddr,
+ uint32_t yiaddr)
+{
+ struct l_dhcp_lease *lease = NULL;
+ int ret;
+
+ ret = get_lease(server, yiaddr, chaddr, &lease);
+ if (ret != 0)
+ return NULL;
+
+ memset(lease, 0, sizeof(*lease));
+
+ memcpy(lease->mac, chaddr, ETH_ALEN);
+ lease->address = yiaddr;
+
+ if (expire == 0)
+ lease->lifetime = l_time_to_secs(l_time_now()) +
+ server->lease_seconds;
+ else
+ lease->lifetime = expire;
+
+ l_queue_insert(server->lease_list, lease, compare_lifetime, NULL);
+
+ SERVER_DEBUG("added lease IP %s for "MAC " lifetime=%u",
+ IP_STR(yiaddr), MAC_STR(chaddr),
+ lease->lifetime);
+
+ return lease;
+}
+
+static bool match_lease_ip(const void *data, const void *user_data)
+{
+ const struct l_dhcp_lease *lease = data;
+
+ return lease->address == L_PTR_TO_UINT(user_data);
+}
+
+static struct l_dhcp_lease *find_lease_by_ip(struct l_dhcp_server *server,
+ uint32_t nip)
+{
+ return l_queue_find(server->lease_list, match_lease_ip,
+ L_UINT_TO_PTR(nip));
+}
+
+static bool check_requested_ip(struct l_dhcp_server *server,
+ uint32_t requested_nip)
+{
+ struct l_dhcp_lease *lease;
+
+ if (requested_nip == 0)
+ return false;
+
+ if (ntohl(requested_nip) < server->start_ip)
+ return false;
+
+ if (htonl(requested_nip) > server->end_ip)
+ return false;
+
+ lease = find_lease_by_ip(server, requested_nip);
+ if (!lease)
+ return true;
+
+ if (!is_expired_lease(lease))
+ return false;
+
+ return true;
+}
+
+/* Check if the IP is taken; if it is, add it to the lease table */
+static bool arp_check(uint32_t ip, const uint8_t *safe_mac)
+{
+ /* TODO: Add ARP checking */
+ return true;
+}
+
+static uint32_t find_free_or_expired_ip(struct l_dhcp_server *server,
+ const uint8_t *safe_mac)
+{
+ uint32_t ip_addr;
+ struct l_dhcp_lease *lease;
+
+ for (ip_addr = server->start_ip; ip_addr <= server->end_ip; ip_addr++) {
+ /* Get IP in network order to return/check for matches */
+ uint32_t ip_nl = htonl(ip_addr);
+
+ /* e.g. 192.168.55.0 */
+ if ((ip_addr & 0xff) == 0)
+ continue;
+
+ /* e.g. 192.168.55.255 */
+ if ((ip_addr & 0xff) == 0xff)
+ continue;
+
+ lease = find_lease_by_ip(server, ip_nl);
+ if (lease)
+ continue;
+
+ if (arp_check(ip_nl, safe_mac))
+ return ip_nl;
+ }
+
+ lease = l_queue_peek_tail(server->lease_list);
+ if (!lease)
+ return 0;
+
+ if (!is_expired_lease(lease))
+ return 0;
+
+ if (!arp_check(lease->address, safe_mac))
+ return 0;
+
+ return lease->address;
+}
+
+static void server_message_init(struct l_dhcp_server *server,
+ const struct dhcp_message *client_msg,
+ struct dhcp_message *reply)
+{
+ reply->xid = client_msg->xid;
+ memcpy(reply->chaddr, client_msg->chaddr, sizeof(client_msg->chaddr));
+ reply->flags = client_msg->flags;
+ reply->giaddr = client_msg->giaddr;
+ reply->ciaddr = client_msg->ciaddr;
+}
+
+static void add_server_options(struct l_dhcp_server *server,
+ struct dhcp_message_builder *builder)
+{
+ int i;
+
+ if (server->netmask)
+ _dhcp_message_builder_append(builder, L_DHCP_OPTION_SUBNET_MASK,
+ 4, &server->netmask);
+
+ if (server->gateway)
+ _dhcp_message_builder_append(builder, L_DHCP_OPTION_ROUTER,
+ 4, &server->gateway);
+
+ if (server->dns_list) {
+ for (i = 0; server->dns_list[i]; i++);
+
+ _dhcp_message_builder_append(builder,
+ L_DHCP_OPTION_DOMAIN_NAME_SERVER,
+ i * 4, server->dns_list);
+ }
+}
+
+static void send_offer(struct l_dhcp_server *server,
+ const struct dhcp_message *client_msg,
+ struct l_dhcp_lease *lease, uint32_t requested_ip)
+{
+ struct dhcp_message_builder builder;
+ size_t len = sizeof(struct dhcp_message) + DHCP_MIN_OPTIONS_SIZE;
+ L_AUTO_FREE_VAR(struct dhcp_message *, reply);
+ uint32_t lease_time = L_CPU_TO_BE32(server->lease_seconds);
+
+ reply = (struct dhcp_message *) l_new(uint8_t, len);
+
+ if (lease)
+ reply->yiaddr = lease->address;
+ else if (check_requested_ip(server, requested_ip))
+ reply->yiaddr = requested_ip;
+ else
+ reply->yiaddr = find_free_or_expired_ip(server,
+ client_msg->chaddr);
+
+ if (!reply->yiaddr) {
+ SERVER_DEBUG("Could not find lease or send offer");
+ return;
+ }
+
+ lease = add_lease(server, OFFER_TIME, client_msg->chaddr,
+ reply->yiaddr);
+ if (!lease) {
+ SERVER_DEBUG("No free IP addresses, OFFER abandoned");
+ return;
+ }
+
+ server_message_init(server, client_msg, reply);
+
+ _dhcp_message_builder_init(&builder, reply, len,
+ DHCP_MESSAGE_TYPE_OFFER);
+
+ _dhcp_message_builder_append(&builder,
+ L_DHCP_OPTION_IP_ADDRESS_LEASE_TIME,
+ 4, &lease_time);
+
+ _dhcp_message_builder_append(&builder, L_DHCP_OPTION_SERVER_IDENTIFIER,
+ 4, &server->address);
+
+ add_server_options(server, &builder);
+
+ _dhcp_message_builder_finalize(&builder, &len);
+
+ SERVER_DEBUG("Sending OFFER of %s to "MAC, IP_STR(reply->yiaddr),
+ MAC_STR(reply->chaddr));
+
+ if (server->transport->l2_send(server->transport, server->address,
+ DHCP_PORT_SERVER,
+ reply->ciaddr, DHCP_PORT_CLIENT,
+ reply->chaddr, reply, len) < 0)
+ SERVER_DEBUG("Failed to send OFFER");
+}
+
static void listener_event(const void *data, size_t len, void *user_data)
{
+ struct l_dhcp_server *server = user_data;
+ const struct dhcp_message *message = data;
+ struct dhcp_message_iter iter;
+ uint8_t t, l;
+ const void *v;
+ struct l_dhcp_lease *lease;
+ uint8_t type = 0;
+ uint32_t server_id_opt = 0;
+ uint32_t requested_ip_opt = 0;
+
+ SERVER_DEBUG("");
+
+ if (!_dhcp_message_iter_init(&iter, message, len))
+ return;
+
+ while (_dhcp_message_iter_next(&iter, &t, &l, &v)) {
+ switch (t) {
+ case DHCP_OPTION_MESSAGE_TYPE:
+ if (l == 1)
+ type = l_get_u8(v);
+
+ break;
+ case L_DHCP_OPTION_SERVER_IDENTIFIER:
+ if (l == 4)
+ server_id_opt = l_get_u32(v);
+
+ if (server->address != server_id_opt)
+ return;
+
+ break;
+ case L_DHCP_OPTION_REQUESTED_IP_ADDRESS:
+ if (l == 4)
+ requested_ip_opt = l_get_u32(v);
+
+ break;
+ }
+ }
+
+ if (type == 0)
+ return;
+
+ lease = find_lease_by_mac(server, message->chaddr);
+ if (!lease)
+ SERVER_DEBUG("No lease found for "MAC,
+ MAC_STR(message->chaddr));
+
+ switch (type) {
+ case DHCP_MESSAGE_TYPE_DISCOVER:
+ SERVER_DEBUG("Received DISCOVER, requested IP %s",
+ IP_STR(requested_ip_opt));
+
+ send_offer(server, message, lease, requested_ip_opt);
+
+ break;
+ }
}
bool _dhcp_server_set_transport(struct l_dhcp_server *server,
--
2.26.2
4 months, 1 week
[PATCH 1/2] build: pass -no-undefined properly
by Ross Burton
From: Ross Burton <ross.burton(a)arm.com>
-no-undefined was added to the libell.la LDFLAGS in commit 8391d72d,
back in 2012, as part of adding versioning. I believe there was some
confusion here as passing -no-undefined to libtool is different to
passing -no-undefined to the linker. The former changes libtool's
behaviour on Windows hosts related to static libraries, the latter will
warn if symbols are used but not defined.
---
Makefile.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 9b3e3c9..7518c6a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -141,7 +141,7 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/icmp6.c \
ell/icmp6-private.h
-ell_libell_la_LDFLAGS = -no-undefined \
+ell_libell_la_LDFLAGS = -Wl,--no-undefined \
-Wl,--version-script=$(top_srcdir)/ell/ell.sym \
-version-info $(ELL_CURRENT):$(ELL_REVISION):$(ELL_AGE)
--
2.28.0
4 months, 1 week
[PATCH 1/2] io: Always call read handler on EPOLLIN
by Inga Stotland
When detecting EPOLLIN, always invoke read handler first.
This ensures that even when error conditions (i.e., EPOLLHUP
and/or EPOLLERR) are encountered, any residual data is still
delivered to the client.
---
ell/io.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/ell/io.c b/ell/io.c
index 41ff6dd..a9e0a38 100644
--- a/ell/io.c
+++ b/ell/io.c
@@ -111,14 +111,6 @@ static void io_callback(int fd, uint32_t events, void *user_data)
{
struct l_io *io = user_data;
- if (unlikely(events & (EPOLLERR | EPOLLHUP))) {
- l_util_debug(io->debug_handler, io->debug_data,
- "disconnect event <%p>", io);
- watch_remove(io->fd, !io->close_on_destroy);
- io_closed(io);
- return;
- }
-
if ((events & EPOLLIN) && io->read_handler) {
l_util_debug(io->debug_handler, io->debug_data,
"read event <%p>", io);
@@ -142,6 +134,14 @@ static void io_callback(int fd, uint32_t events, void *user_data)
}
}
+ if (unlikely(events & (EPOLLERR | EPOLLHUP))) {
+ l_util_debug(io->debug_handler, io->debug_data,
+ "disconnect event <%p>", io);
+ watch_remove(io->fd, !io->close_on_destroy);
+ io_closed(io);
+ return;
+ }
+
if ((events & EPOLLOUT) && io->write_handler) {
l_util_debug(io->debug_handler, io->debug_data,
"write event <%p>", io);
--
2.26.2
4 months, 1 week
[PATCH v6 1/6] dhcp-server: process DISCOVER and send OFFER
by James Prestwood
Add handling of DISCOVER messages and ability to send offers.
---
ell/dhcp-server.c | 330 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 330 insertions(+)
v6:
* Moved MAC_BCAST_ADDR to the patch where its used
* Removed NULL check from l_new
* Fixed some uses of htonl vs ntohl for consistency
* Converted the IP in find_free_or_expired_ip only
once rather than 3 separate times.
diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index 6b7e483..1af7465 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -41,6 +41,9 @@
/* 8 hours */
#define DEFAULT_DHCP_LEASE_SEC (8*60*60)
+/* 5 minutes */
+#define OFFER_TIME (5*60)
+
struct l_dhcp_server {
bool started;
int ifindex;
@@ -82,8 +85,335 @@ struct l_dhcp_server {
l_util_debug(server->debug_handler, server->debug_data, \
"%s:%i " fmt, __func__, __LINE__, ## args)
+static bool is_expired_lease(struct l_dhcp_lease *lease)
+{
+ if (lease->lifetime < l_time_to_secs(l_time_now()))
+ return true;
+
+ return false;
+}
+
+static bool match_lease_mac(const void *data, const void *user_data)
+{
+ const struct l_dhcp_lease *lease = data;
+ const uint8_t *mac = user_data;
+
+ return !memcmp(lease->mac, mac, 6);
+}
+
+static struct l_dhcp_lease *find_lease_by_mac(struct l_dhcp_server *server,
+ const uint8_t *mac)
+{
+ return l_queue_find(server->lease_list, match_lease_mac, mac);
+}
+
+/* Clear the old lease and create the new one */
+static int get_lease(struct l_dhcp_server *server, uint32_t yiaddr,
+ const uint8_t *mac,
+ struct l_dhcp_lease **lease_out)
+{
+ struct l_dhcp_lease *lease;
+
+ if (yiaddr == 0)
+ return -ENXIO;
+
+ if (ntohl(yiaddr) < server->start_ip)
+ return -ENXIO;
+
+ if (ntohl(yiaddr) > server->end_ip)
+ return -ENXIO;
+
+ if (l_memeq(mac, ETH_ALEN, 0xff))
+ return -ENXIO;
+
+ if (l_memeqzero(mac, ETH_ALEN))
+ return -ENXIO;
+
+ lease = find_lease_by_mac(server, mac);
+
+ if (lease) {
+ l_queue_remove(server->lease_list, lease);
+
+ *lease_out = lease;
+
+ return 0;
+ }
+
+ *lease_out = l_new(struct l_dhcp_lease, 1);
+
+ return 0;
+}
+
+static int compare_lifetime(const void *a, const void *b, void *user_data)
+{
+ const struct l_dhcp_lease *lease1 = a;
+ const struct l_dhcp_lease *lease2 = b;
+
+ return lease2->lifetime - lease1->lifetime;
+}
+
+static struct l_dhcp_lease *add_lease(struct l_dhcp_server *server,
+ uint32_t expire, const uint8_t *chaddr,
+ uint32_t yiaddr)
+{
+ struct l_dhcp_lease *lease = NULL;
+ int ret;
+
+ ret = get_lease(server, yiaddr, chaddr, &lease);
+ if (ret != 0)
+ return NULL;
+
+ memset(lease, 0, sizeof(*lease));
+
+ memcpy(lease->mac, chaddr, ETH_ALEN);
+ lease->address = yiaddr;
+
+ if (expire == 0)
+ lease->lifetime = l_time_to_secs(l_time_now()) +
+ server->lease_seconds;
+ else
+ lease->lifetime = expire;
+
+ l_queue_insert(server->lease_list, lease, compare_lifetime, NULL);
+
+ SERVER_DEBUG("added lease IP %s for "MAC " lifetime=%u",
+ IP_STR(yiaddr), MAC_STR(chaddr),
+ lease->lifetime);
+
+ return lease;
+}
+
+static bool match_lease_ip(const void *data, const void *user_data)
+{
+ const struct l_dhcp_lease *lease = data;
+
+ return lease->address == L_PTR_TO_UINT(user_data);
+}
+
+static struct l_dhcp_lease *find_lease_by_ip(struct l_dhcp_server *server,
+ uint32_t nip)
+{
+ return l_queue_find(server->lease_list, match_lease_ip,
+ L_UINT_TO_PTR(nip));
+}
+
+static bool check_requested_ip(struct l_dhcp_server *server,
+ uint32_t requested_nip)
+{
+ struct l_dhcp_lease *lease;
+
+ if (requested_nip == 0)
+ return false;
+
+ if (ntohl(requested_nip) < server->start_ip)
+ return false;
+
+ if (htonl(requested_nip) > server->end_ip)
+ return false;
+
+ lease = find_lease_by_ip(server, requested_nip);
+ if (!lease)
+ return true;
+
+ if (!is_expired_lease(lease))
+ return false;
+
+ return true;
+}
+
+/* Check if the IP is taken; if it is, add it to the lease table */
+static bool arp_check(uint32_t ip, const uint8_t *safe_mac)
+{
+ /* TODO: Add ARP checking */
+ return true;
+}
+
+static uint32_t find_free_or_expired_ip(struct l_dhcp_server *server,
+ const uint8_t *safe_mac)
+{
+ uint32_t ip_addr;
+ struct l_dhcp_lease *lease;
+
+ for (ip_addr = server->start_ip; ip_addr <= server->end_ip; ip_addr++) {
+ /* Get IP in network order to return/check for matches */
+ uint32_t ip_nl = htonl(ip_addr);
+
+ /* e.g. 192.168.55.0 */
+ if ((ip_addr & 0xff) == 0)
+ continue;
+
+ /* e.g. 192.168.55.255 */
+ if ((ip_addr & 0xff) == 0xff)
+ continue;
+
+ lease = find_lease_by_ip(server, ip_nl);
+ if (lease)
+ continue;
+
+ if (arp_check(ip_nl, safe_mac))
+ return ip_nl;
+ }
+
+ lease = l_queue_peek_tail(server->lease_list);
+ if (!lease)
+ return 0;
+
+ if (!is_expired_lease(lease))
+ return 0;
+
+ if (!arp_check(lease->address, safe_mac))
+ return 0;
+
+ return lease->address;
+}
+
+static void server_message_init(struct l_dhcp_server *server,
+ const struct dhcp_message *client_msg,
+ struct dhcp_message *reply)
+{
+ reply->xid = client_msg->xid;
+ memcpy(reply->chaddr, client_msg->chaddr, sizeof(client_msg->chaddr));
+ reply->flags = client_msg->flags;
+ reply->giaddr = client_msg->giaddr;
+ reply->ciaddr = client_msg->ciaddr;
+}
+
+static void add_server_options(struct l_dhcp_server *server,
+ struct dhcp_message_builder *builder)
+{
+ int i;
+
+ if (server->netmask)
+ _dhcp_message_builder_append(builder, L_DHCP_OPTION_SUBNET_MASK,
+ 4, &server->netmask);
+
+ if (server->gateway)
+ _dhcp_message_builder_append(builder, L_DHCP_OPTION_ROUTER,
+ 4, &server->gateway);
+
+ if (server->dns_list) {
+ for (i = 0; server->dns_list[i]; i++);
+
+ _dhcp_message_builder_append(builder,
+ L_DHCP_OPTION_DOMAIN_NAME_SERVER,
+ i * 4, server->dns_list);
+ }
+}
+
+static void send_offer(struct l_dhcp_server *server,
+ const struct dhcp_message *client_msg,
+ struct l_dhcp_lease *lease, uint32_t requested_ip)
+{
+ struct dhcp_message_builder builder;
+ size_t len = sizeof(struct dhcp_message) + DHCP_MIN_OPTIONS_SIZE;
+ L_AUTO_FREE_VAR(struct dhcp_message *, reply);
+ uint32_t lease_time = L_CPU_TO_BE32(server->lease_seconds);
+
+ reply = (struct dhcp_message *) l_new(uint8_t, len);
+
+ if (lease)
+ reply->yiaddr = lease->address;
+ else if (check_requested_ip(server, requested_ip))
+ reply->yiaddr = requested_ip;
+ else
+ reply->yiaddr = find_free_or_expired_ip(server,
+ client_msg->chaddr);
+
+ if (!reply->yiaddr) {
+ SERVER_DEBUG("Could not find lease or send offer");
+ return;
+ }
+
+ lease = add_lease(server, OFFER_TIME, client_msg->chaddr,
+ reply->yiaddr);
+ if (!lease) {
+ SERVER_DEBUG("No free IP addresses, OFFER abandoned");
+ return;
+ }
+
+ server_message_init(server, client_msg, reply);
+
+ _dhcp_message_builder_init(&builder, reply, len,
+ DHCP_MESSAGE_TYPE_OFFER);
+
+ _dhcp_message_builder_append(&builder,
+ L_DHCP_OPTION_IP_ADDRESS_LEASE_TIME,
+ 4, &lease_time);
+
+ _dhcp_message_builder_append(&builder, L_DHCP_OPTION_SERVER_IDENTIFIER,
+ 4, &server->address);
+
+ add_server_options(server, &builder);
+
+ _dhcp_message_builder_finalize(&builder, &len);
+
+ SERVER_DEBUG("Sending OFFER of %s to "MAC, IP_STR(reply->yiaddr),
+ MAC_STR(reply->chaddr));
+
+ if (server->transport->l2_send(server->transport, server->address,
+ DHCP_PORT_SERVER,
+ reply->ciaddr, DHCP_PORT_CLIENT,
+ reply->chaddr, reply, len) < 0)
+ SERVER_DEBUG("Failed to send OFFER");
+}
+
static void listener_event(const void *data, size_t len, void *user_data)
{
+ struct l_dhcp_server *server = user_data;
+ const struct dhcp_message *message = data;
+ struct dhcp_message_iter iter;
+ uint8_t t, l;
+ const void *v;
+ struct l_dhcp_lease *lease;
+ uint8_t type = 0;
+ uint32_t server_id_opt = 0;
+ uint32_t requested_ip_opt = 0;
+
+ SERVER_DEBUG("");
+
+ if (!_dhcp_message_iter_init(&iter, message, len))
+ return;
+
+ while (_dhcp_message_iter_next(&iter, &t, &l, &v)) {
+ switch (t) {
+ case DHCP_OPTION_MESSAGE_TYPE:
+ if (l == 1)
+ type = l_get_u8(v);
+
+ break;
+ case L_DHCP_OPTION_SERVER_IDENTIFIER:
+ if (l == 4)
+ server_id_opt = l_get_u32(v);
+
+ if (server->address != server_id_opt)
+ return;
+
+ break;
+ case L_DHCP_OPTION_REQUESTED_IP_ADDRESS:
+ if (l == 4)
+ requested_ip_opt = l_get_u32(v);
+
+ break;
+ }
+ }
+
+ if (type == 0)
+ return;
+
+ lease = find_lease_by_mac(server, message->chaddr);
+ if (!lease)
+ SERVER_DEBUG("No lease found for "MAC,
+ MAC_STR(message->chaddr));
+
+ switch (type) {
+ case DHCP_MESSAGE_TYPE_DISCOVER:
+ SERVER_DEBUG("Received DISCOVER, requested IP %s",
+ IP_STR(requested_ip_opt));
+
+ send_offer(server, message, lease, requested_ip_opt);
+
+ break;
+ }
}
bool _dhcp_server_set_transport(struct l_dhcp_server *server,
--
2.26.2
4 months, 1 week
[PATCH v5 01/12] util: add l_memeq/l_memeqzero
by James Prestwood
Utility functions for testing if memory equals a byte, or zero.
---
ell/ell.sym | 2 ++
ell/util.h | 16 ++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/ell/ell.sym b/ell/ell.sym
index 5268b48..0b0a6cc 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -20,6 +20,8 @@ global:
l_util_hexdumpv;
l_util_debug;
l_util_get_debugfs_path;
+ l_memeq;
+ l_memeqzero;
/* test */
l_test_init;
l_test_run;
diff --git a/ell/util.h b/ell/util.h
index ca894c7..a8b52ad 100644
--- a/ell/util.h
+++ b/ell/util.h
@@ -391,6 +391,22 @@ static inline int l_secure_memcmp(const void *a, const void *b,
return res;
}
+static inline bool l_memeq(const uint8_t *field, size_t size, uint8_t byte)
+{
+ size_t i;
+
+ for (i = 0; i < size; i++)
+ if (field[i] != byte)
+ return false;
+
+ return true;
+}
+
+static inline bool l_memeqzero(const uint8_t *field, size_t size)
+{
+ return l_memeq(field, size, 0);
+}
+
#ifdef __cplusplus
}
#endif
--
2.26.2
4 months, 1 week
[PATCH v4 01/11] dhcp-server: basic DHCP server skeleton
by James Prestwood
---
Makefile.am | 1 +
ell/dhcp-server.c | 347 ++++++++++++++++++++++++++++++++++++++++++++++
ell/dhcp.h | 36 +++++
ell/ell.sym | 13 ++
4 files changed, 397 insertions(+)
create mode 100644 ell/dhcp-server.c
v4:
* Fixed endianness issues when auto-assigning IP range
diff --git a/Makefile.am b/Makefile.am
index beba535..9bdf4dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -128,6 +128,7 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/dhcp6-transport.c \
ell/dhcp6-lease.c \
ell/dhcp-util.c \
+ ell/dhcp-server.c \
ell/cert.c \
ell/cert-private.h \
ell/ecc-private.h \
diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
new file mode 100644
index 0000000..97479ae
--- /dev/null
+++ b/ell/dhcp-server.c
@@ -0,0 +1,347 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <net/ethernet.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <time.h>
+
+#include "private.h"
+#include "time.h"
+#include "net.h"
+#include "dhcp.h"
+#include "dhcp-private.h"
+#include "queue.h"
+#include "util.h"
+#include "strv.h"
+
+/* 8 hours */
+#define DEFAULT_DHCP_LEASE_SEC (8*60*60)
+
+struct l_dhcp_server {
+ bool started;
+ int ifindex;
+ char *ifname;
+ uint32_t start_ip;
+ uint32_t end_ip;
+ uint32_t address;
+ uint32_t netmask;
+ uint32_t gateway;
+ uint32_t *dns_list;
+ uint32_t lease_seconds;
+
+ struct l_queue *lease_list;
+
+ l_dhcp_debug_cb_t debug_handler;
+ void *debug_data;
+
+ l_dhcp_server_event_cb_t event_handler;
+ void *user_data;
+ l_dhcp_destroy_cb_t event_destroy;
+};
+
+#define MAC "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_STR(a) a[0], a[1], a[2], a[3], a[4], a[5]
+
+#define IP_STR(uint_ip) \
+({ \
+ struct in_addr _in; \
+ char *_out; \
+ _in.s_addr = uint_ip; \
+ _out = inet_ntoa(_in); \
+ _out; \
+})
+
+#define SERVER_DEBUG(fmt, args...) \
+ l_util_debug(server->debug_handler, server->debug_data, \
+ "%s:%i " fmt, __func__, __LINE__, ## args)
+
+LIB_EXPORT struct l_dhcp_server *l_dhcp_server_new(int ifindex)
+{
+ struct l_dhcp_server *server = l_new(struct l_dhcp_server, 1);
+ if (!server)
+ return NULL;
+
+ server->lease_list = l_queue_new();
+
+ server->started = false;
+
+ server->lease_seconds = DEFAULT_DHCP_LEASE_SEC;
+
+ server->ifindex = ifindex;
+ server->debug_handler = NULL;
+ server->debug_data = NULL;
+
+ return server;
+}
+
+LIB_EXPORT void l_dhcp_server_destroy(struct l_dhcp_server *server)
+{
+ if (unlikely(!server))
+ return;
+
+ l_dhcp_server_stop(server);
+
+ if (server->event_destroy)
+ server->event_destroy(server->user_data);
+
+ l_free(server->ifname);
+
+ l_queue_destroy(server->lease_list,
+ (l_queue_destroy_func_t) _dhcp_lease_free);
+
+ if (server->dns_list)
+ l_free(server->dns_list);
+
+ l_free(server);
+}
+
+LIB_EXPORT bool l_dhcp_server_start(struct l_dhcp_server *server)
+{
+ struct in_addr ia;
+
+ if (unlikely(!server))
+ return false;
+
+ if (server->started)
+ return false;
+
+ if (!server->address) {
+ if (!l_net_get_address(server->ifindex, &ia))
+ return false;
+
+ server->address = ia.s_addr;
+ }
+
+ /* Assign a default gateway if not already set */
+ if (!server->gateway)
+ server->gateway = server->address;
+
+ /* Assign a default netmask if not already */
+ if (!server->netmask) {
+ if (inet_aton("255.255.255.0", &ia) < 0)
+ return false;
+
+ server->netmask = ia.s_addr;
+ }
+
+ /*
+ * Assign a default ip range if not already. This will default to
+ * server->address + 1 ... 254
+ */
+ if (!server->start_ip) {
+ uint8_t *ptr = (uint8_t *) &server->start_ip;
+
+ server->start_ip = server->address;
+ ptr[3] += 1;
+
+ ptr = (uint8_t *) &server->end_ip;
+ server->end_ip = server->address;
+ ptr[3] = 254;
+ }
+
+ if (!server->ifname) {
+ server->ifname = l_net_get_name(server->ifindex);
+
+ if (!server->ifname)
+ return false;
+ }
+
+ SERVER_DEBUG("Starting DHCP server on %s", server->ifname);
+
+ server->started = true;
+
+ return true;
+}
+
+LIB_EXPORT bool l_dhcp_server_stop(struct l_dhcp_server *server)
+{
+ if (unlikely(!server))
+ return false;
+
+ if (!server->started)
+ return true;
+
+ server->started = false;
+
+ /* TODO: Add ability to save leases */
+
+ return true;
+}
+
+LIB_EXPORT bool l_dhcp_server_set_ip_range(struct l_dhcp_server *server,
+ const char *start_ip,
+ const char *end_ip)
+{
+ struct in_addr _host_addr;
+ uint32_t start;
+
+ if (unlikely(!server || !start_ip || !end_ip))
+ return false;
+
+ if (inet_aton((const char *)start_ip, &_host_addr) == 0)
+ return false;
+
+ start = _host_addr.s_addr;
+
+ if (inet_aton((const char *) end_ip, &_host_addr) == 0)
+ return false;
+
+ server->start_ip = start;
+ server->end_ip = _host_addr.s_addr;
+
+ return true;
+}
+
+LIB_EXPORT bool l_dhcp_server_set_debug(struct l_dhcp_server *server,
+ l_dhcp_debug_cb_t function,
+ void *user_data, l_dhcp_destroy_cb_t destory)
+{
+ if (unlikely(!server))
+ return false;
+
+ server->debug_handler = function;
+ server->debug_data = user_data;
+
+ return true;
+}
+
+LIB_EXPORT bool l_dhcp_server_set_lease_time(struct l_dhcp_server *server,
+ unsigned int lease_time)
+{
+ if (unlikely(!server))
+ return false;
+
+ server->lease_seconds = lease_time;
+
+ return true;
+}
+
+LIB_EXPORT bool l_dhcp_server_set_event_handler(struct l_dhcp_server *server,
+ l_dhcp_server_event_cb_t handler,
+ void *user_data,
+ l_dhcp_destroy_cb_t destroy)
+{
+ if (unlikely(!server))
+ return false;
+
+ server->event_handler = handler;
+ server->user_data = user_data;
+ server->event_destroy = destroy;
+
+ return true;
+}
+
+LIB_EXPORT bool l_dhcp_server_set_ip_address(struct l_dhcp_server *server,
+ const char *ip)
+{
+ struct in_addr ia;
+
+ if (unlikely(!server))
+ return false;
+
+ if (inet_aton(ip, &ia) < 0)
+ return false;
+
+ server->address = ia.s_addr;
+
+ return true;
+}
+
+LIB_EXPORT bool l_dhcp_server_set_interface_name(struct l_dhcp_server *server,
+ const char *ifname)
+{
+ if (unlikely(!server || !ifname))
+ return false;
+
+ l_free(server->ifname);
+ server->ifname = l_strdup(ifname);
+
+ return true;
+}
+
+LIB_EXPORT bool l_dhcp_server_set_netmask(struct l_dhcp_server *server,
+ const char *mask)
+{
+ struct in_addr ia;
+
+ if (unlikely(!server || !mask))
+ return false;
+
+ if (inet_aton(mask, &ia) < 0)
+ return false;
+
+ server->netmask = ia.s_addr;
+
+ return true;
+}
+
+LIB_EXPORT bool l_dhcp_server_set_gateway(struct l_dhcp_server *server,
+ const char *ip)
+{
+ struct in_addr ia;
+
+ if (unlikely(!server || !ip))
+ return false;
+
+ if (inet_aton(ip, &ia) < 0)
+ return false;
+
+ server->gateway = ia.s_addr;
+
+ return true;
+}
+
+LIB_EXPORT bool l_dhcp_server_set_dns(struct l_dhcp_server *server, char **dns)
+{
+ unsigned int i;
+ uint32_t *dns_list;
+
+ if (unlikely(!server || !dns))
+ return false;
+
+ dns_list = l_new(uint32_t, l_strv_length(dns) + 1);
+
+ for (i = 0; dns[i]; i++) {
+ struct in_addr ia;
+
+ if (inet_aton(dns[i], &ia) < 0)
+ goto failed;
+
+ dns_list[i] = ia.s_addr;
+ }
+
+ if (server->dns_list)
+ l_free(server->dns_list);
+
+ server->dns_list = dns_list;
+
+ return true;
+
+failed:
+ l_free(dns_list);
+ return false;
+}
diff --git a/ell/dhcp.h b/ell/dhcp.h
index c78b605..a92f6aa 100644
--- a/ell/dhcp.h
+++ b/ell/dhcp.h
@@ -31,6 +31,7 @@ extern "C" {
struct l_dhcp_client;
struct l_dhcp_lease;
+struct l_dhcp_server;
/* RFC 2132 */
enum l_dhcp_option {
@@ -56,12 +57,22 @@ enum l_dhcp_client_event {
L_DHCP_CLIENT_EVENT_NO_LEASE,
};
+enum l_dhcp_server_event {
+ L_DHCP_SERVER_EVENT_NEW_LEASE,
+ L_DHCP_SERVER_EVENT_LEASE_EXPIRED,
+};
+
typedef void (*l_dhcp_client_event_cb_t)(struct l_dhcp_client *client,
enum l_dhcp_client_event event,
void *userdata);
typedef void (*l_dhcp_debug_cb_t)(const char *str, void *user_data);
typedef void (*l_dhcp_destroy_cb_t)(void *userdata);
+typedef void (*l_dhcp_server_event_cb_t)(struct l_dhcp_server *server,
+ enum l_dhcp_server_event event,
+ void *user_data,
+ const struct l_dhcp_lease *lease);
+
struct l_dhcp_client *l_dhcp_client_new(uint32_t ifindex);
bool l_dhcp_client_add_request_option(struct l_dhcp_client *client,
uint8_t option);
@@ -89,6 +100,7 @@ bool l_dhcp_client_set_debug(struct l_dhcp_client *client,
l_dhcp_debug_cb_t function,
void *user_data, l_dhcp_destroy_cb_t destroy);
+
char *l_dhcp_lease_get_address(const struct l_dhcp_lease *lease);
char *l_dhcp_lease_get_gateway(const struct l_dhcp_lease *lease);
char *l_dhcp_lease_get_netmask(const struct l_dhcp_lease *lease);
@@ -101,6 +113,30 @@ const uint8_t *l_dhcp_lease_get_mac(const struct l_dhcp_lease *lease);
uint32_t l_dhcp_lease_get_t1(const struct l_dhcp_lease *lease);
uint32_t l_dhcp_lease_get_t2(const struct l_dhcp_lease *lease);
uint32_t l_dhcp_lease_get_lifetime(const struct l_dhcp_lease *lease);
+
+struct l_dhcp_server *l_dhcp_server_new(int ifindex);
+void l_dhcp_server_destroy(struct l_dhcp_server *server);
+bool l_dhcp_server_start(struct l_dhcp_server *server);
+bool l_dhcp_server_stop(struct l_dhcp_server *server);
+bool l_dhcp_server_set_ip_range(struct l_dhcp_server *server,
+ const char *start_ip,
+ const char *end_ip);
+bool l_dhcp_server_set_debug(struct l_dhcp_server *server,
+ l_dhcp_debug_cb_t function,
+ void *user_data, l_dhcp_destroy_cb_t destory);
+bool l_dhcp_server_set_event_handler(struct l_dhcp_server *server,
+ l_dhcp_server_event_cb_t handler,
+ void *user_data,
+ l_dhcp_destroy_cb_t destroy);
+bool l_dhcp_server_set_lease_time(struct l_dhcp_server *server,
+ unsigned int lease_time);
+bool l_dhcp_server_set_interface_name(struct l_dhcp_server *server,
+ const char *ifname);
+bool l_dhcp_server_set_ip_address(struct l_dhcp_server *server,
+ const char *ip);
+bool l_dhcp_server_set_netmask(struct l_dhcp_server *server, const char *mask);
+bool l_dhcp_server_set_gateway(struct l_dhcp_server *server, const char *ip);
+bool l_dhcp_server_set_dns(struct l_dhcp_server *server, char **dns);
#ifdef __cplusplus
}
#endif
diff --git a/ell/ell.sym b/ell/ell.sym
index 5268b48..7a920ed 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -242,6 +242,19 @@ global:
l_dhcp_client_stop;
l_dhcp_client_set_event_handler;
l_dhcp_client_set_debug;
+ l_dhcp_server_new;
+ l_dhcp_server_destroy;
+ l_dhcp_server_start;
+ l_dhcp_server_stop;
+ l_dhcp_server_set_ip_range;
+ l_dhcp_server_set_debug;
+ l_dhcp_server_set_lease_time;
+ l_dhcp_server_set_event_handler;
+ l_dhcp_server_set_ip_address;
+ l_dhcp_server_set_interface_name;
+ l_dhcp_server_set_netmaks;
+ l_dhcp_server_set_gateway;
+ l_dhcp_server_set_dns;
/* dhcp6 */
l_dhcp6_client_new;
l_dhcp6_client_destroy;
--
2.26.2
4 months, 2 weeks
[PATCH v3 01/14] dhcp-transport: rework 'broadcast' op to allow unicast
by James Prestwood
Functionally this was being used as a broadcast only because the
destination address was a broadcast address. But providing a
MAC address would effectively turn this into a unicast over l2
which DHCP server requires.
To support server a destination MAC address was added to the
arguments and if NULL the destination will be set to a broadcast
address. The name of the op was changed to 'l2_send' to better
describe the new behavior. All client code will remain nearly the
same (just name changes) except having to set the destination MAC
to NULL indicating it is a broadcast.
---
ell/dhcp-private.h | 3 ++-
ell/dhcp-transport.c | 10 +++++++---
ell/dhcp.c | 7 ++++---
3 files changed, 13 insertions(+), 7 deletions(-)
v3:
* Reworded commit description to be more clear that the original op
was a broadcast only operation and was modified to work with
both broadcast and unicast on l2
diff --git a/ell/dhcp-private.h b/ell/dhcp-private.h
index 990162c..68ad7c2 100644
--- a/ell/dhcp-private.h
+++ b/ell/dhcp-private.h
@@ -106,9 +106,10 @@ typedef void (*dhcp_transport_rx_cb_t)(const void *, size_t, void *);
struct dhcp_transport {
int (*open)(struct dhcp_transport *s, uint32_t xid);
- int (*broadcast)(struct dhcp_transport *transport,
+ int (*l2_send)(struct dhcp_transport *transport,
uint32_t saddr, uint16_t sport,
uint32_t daddr, uint16_t dport,
+ const uint8_t *dest_mac,
const void *data, size_t len);
int (*bind)(struct dhcp_transport *transport, uint32_t saddr);
int (*send)(struct dhcp_transport *transport,
diff --git a/ell/dhcp-transport.c b/ell/dhcp-transport.c
index 1fa84b2..71d0c47 100644
--- a/ell/dhcp-transport.c
+++ b/ell/dhcp-transport.c
@@ -194,9 +194,10 @@ static void dhcp_set_ip_udp_headers(struct iphdr *ip, struct udphdr *udp,
ip->check = _dhcp_checksumv(iov, 1);
}
-static int _dhcp_default_transport_broadcast(struct dhcp_transport *s,
+static int _dhcp_default_transport_l2_send(struct dhcp_transport *s,
uint32_t saddr, uint16_t sport,
uint32_t daddr, uint16_t dport,
+ const uint8_t *dest_mac,
const void *data, size_t len)
{
struct dhcp_default_transport *transport =
@@ -221,7 +222,10 @@ static int _dhcp_default_transport_broadcast(struct dhcp_transport *s,
addr.sll_protocol = htons(ETH_P_IP);
addr.sll_ifindex = s->ifindex;
addr.sll_halen = ETH_ALEN;
- memset(addr.sll_addr, 0xff, ETH_ALEN);
+ if (!dest_mac)
+ memset(addr.sll_addr, 0xff, ETH_ALEN);
+ else
+ memcpy(addr.sll_addr, dest_mac, ETH_ALEN);
memset(&msg, 0, sizeof(msg));
msg.msg_name = &addr;
@@ -501,7 +505,7 @@ struct dhcp_transport *_dhcp_default_transport_new(uint32_t ifindex,
transport->super.bind = _dhcp_default_transport_bind;
transport->super.close = _dhcp_default_transport_close;
transport->super.send = _dhcp_default_transport_send;
- transport->super.broadcast = _dhcp_default_transport_broadcast;
+ transport->super.l2_send = _dhcp_default_transport_l2_send;
transport->super.ifindex = ifindex;
l_strlcpy(transport->ifname, ifname, IFNAMSIZ);
diff --git a/ell/dhcp.c b/ell/dhcp.c
index f52b470..d75d86f 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -354,9 +354,10 @@ static int dhcp_client_send_discover(struct l_dhcp_client *client)
_dhcp_message_builder_finalize(&builder, &len);
- return client->transport->broadcast(client->transport,
+ return client->transport->l2_send(client->transport,
INADDR_ANY, DHCP_PORT_CLIENT,
INADDR_BROADCAST, DHCP_PORT_SERVER,
+ NULL,
discover, len);
}
@@ -453,10 +454,10 @@ static int dhcp_client_send_request(struct l_dhcp_client *client)
&si, request, len);
}
- return client->transport->broadcast(client->transport,
+ return client->transport->l2_send(client->transport,
INADDR_ANY, DHCP_PORT_CLIENT,
INADDR_BROADCAST, DHCP_PORT_SERVER,
- request, len);
+ NULL, request, len);
}
static void dhcp_client_timeout_resend(struct l_timeout *timeout,
--
2.26.2
4 months, 2 weeks
[PATCH 01/20] net: add l_net_get_address()
by James Prestwood
---
ell/ell.sym | 1 +
ell/net.c | 34 ++++++++++++++++++++++++++++++++++
ell/net.h | 3 +++
3 files changed, 38 insertions(+)
v2:
* Renamed to l_net_get_address and changed to take in_addr out
parameter rather than return the IP as a uint32_t.
diff --git a/ell/ell.sym b/ell/ell.sym
index 7108ce3..b3d5c71 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -368,6 +368,7 @@ global:
l_debug_enable_full;
l_debug_disable;
/* net */
+ l_net_get_address;
l_net_get_mac_address;
l_net_get_name;
l_net_hostname_is_root;
diff --git a/ell/net.c b/ell/net.c
index 0bff535..12e88d8 100644
--- a/ell/net.c
+++ b/ell/net.c
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
+#include <netinet/ip.h>
#include "net.h"
#include "net-private.h"
@@ -336,3 +337,36 @@ char **net_domain_list_parse(const uint8_t *raw, size_t raw_len)
return ret;
}
+
+LIB_EXPORT bool l_net_get_address(int ifindex, struct in_addr *out)
+{
+ struct ifreq ifr;
+ int sk, err;
+ struct sockaddr_in *server_ip;
+ bool ret = false;
+
+ sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (sk < 0)
+ return false;
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_ifindex = ifindex;
+
+ err = ioctl(sk, SIOCGIFNAME, &ifr);
+ if (err < 0)
+ goto done;
+
+ err = ioctl(sk, SIOCGIFADDR, &ifr);
+ if (err < 0)
+ goto done;
+
+ server_ip = (struct sockaddr_in *) &ifr.ifr_addr;
+ out->s_addr = server_ip->sin_addr.s_addr;
+
+ ret = true;
+
+done:
+ close(sk);
+
+ return ret;
+}
diff --git a/ell/net.h b/ell/net.h
index 6808e07..178f13b 100644
--- a/ell/net.h
+++ b/ell/net.h
@@ -26,6 +26,8 @@
#include <stdbool.h>
#include <stdint.h>
+struct in_addr;
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -34,6 +36,7 @@ bool l_net_get_mac_address(uint32_t ifindex, uint8_t *out_addr);
char *l_net_get_name(uint32_t ifindex);
bool l_net_hostname_is_root(const char *hostname);
bool l_net_hostname_is_localhost(const char *hostname);
+bool l_net_get_address(int ifindex, struct in_addr *out);
#ifdef __cplusplus
}
--
2.26.2
4 months, 2 weeks
[PATCH 01/14] net: add l_net_get_ip_address()
by James Prestwood
---
ell/net.c | 32 ++++++++++++++++++++++++++++++++
ell/net.h | 1 +
2 files changed, 33 insertions(+)
diff --git a/ell/net.c b/ell/net.c
index 0bff535..5551779 100644
--- a/ell/net.c
+++ b/ell/net.c
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
+#include <netinet/ip.h>
#include "net.h"
#include "net-private.h"
@@ -336,3 +337,34 @@ char **net_domain_list_parse(const uint8_t *raw, size_t raw_len)
return ret;
}
+
+LIB_EXPORT uint32_t l_net_get_ip_address(int ifindex)
+{
+ struct ifreq ifr;
+ int sk, err;
+ struct sockaddr_in *server_ip;
+ uint32_t ret = 0;
+
+ sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (sk < 0)
+ return 0;
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_ifindex = ifindex;
+
+ err = ioctl(sk, SIOCGIFNAME, &ifr);
+ if (err < 0)
+ goto done;
+
+ err = ioctl(sk, SIOCGIFADDR, &ifr);
+ if (err < 0)
+ goto done;
+
+ server_ip = (struct sockaddr_in *) &ifr.ifr_addr;
+ ret = server_ip->sin_addr.s_addr;
+
+done:
+ close(sk);
+
+ return ret;
+}
diff --git a/ell/net.h b/ell/net.h
index 6808e07..abaf785 100644
--- a/ell/net.h
+++ b/ell/net.h
@@ -34,6 +34,7 @@ bool l_net_get_mac_address(uint32_t ifindex, uint8_t *out_addr);
char *l_net_get_name(uint32_t ifindex);
bool l_net_hostname_is_root(const char *hostname);
bool l_net_hostname_is_localhost(const char *hostname);
+uint32_t l_net_get_ip_address(int ifindex);
#ifdef __cplusplus
}
--
2.26.2
4 months, 2 weeks