All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 1/6] dhcp-server: process DISCOVER and send OFFER
@ 2020-10-20 15:52 James Prestwood
  2020-10-20 15:52 ` [PATCH v7 2/6] dhcp-server: add REQUEST processing James Prestwood
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: James Prestwood @ 2020-10-20 15:52 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 8944 bytes --]

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

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v7 2/6] dhcp-server: add REQUEST processing
  2020-10-20 15:52 [PATCH v7 1/6] dhcp-server: process DISCOVER and send OFFER James Prestwood
@ 2020-10-20 15:52 ` James Prestwood
  2020-10-20 15:52 ` [PATCH v7 3/6] dhcp-server: handle DECLINE messages James Prestwood
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2020-10-20 15:52 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 3590 bytes --]

Handle REQUEST packets and implement ACK/NAK responses.
---
 ell/dhcp-server.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index 1af7465..2008c56 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -44,6 +44,10 @@
 /* 5 minutes  */
 #define OFFER_TIME (5*60)
 
+static const uint8_t MAC_BCAST_ADDR[ETH_ALEN] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
 struct l_dhcp_server {
 	bool started;
 	int ifindex;
@@ -357,6 +361,73 @@ static void send_offer(struct l_dhcp_server *server,
 		SERVER_DEBUG("Failed to send OFFER");
 }
 
+static void send_nak(struct l_dhcp_server *server,
+			const struct dhcp_message *client_msg)
+{
+	struct dhcp_message_builder builder;
+	size_t len = sizeof(struct dhcp_message) + DHCP_MIN_OPTIONS_SIZE;
+	L_AUTO_FREE_VAR(struct dhcp_message *, reply);
+
+	reply = (struct dhcp_message *) l_new(uint8_t, len);
+
+	server_message_init(server, client_msg, reply);
+
+	_dhcp_message_builder_init(&builder, reply, len, DHCP_MESSAGE_TYPE_NAK);
+
+	_dhcp_message_builder_finalize(&builder, &len);
+
+	if (server->transport->l2_send(server->transport, server->address,
+					DHCP_PORT_SERVER, reply->ciaddr,
+					DHCP_PORT_CLIENT, MAC_BCAST_ADDR,
+					reply, len) < 0)
+		SERVER_DEBUG("Failed to send NACK");
+}
+
+static void send_ack(struct l_dhcp_server *server,
+			const struct dhcp_message *client_msg, uint32_t dest)
+{
+	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);
+	struct l_dhcp_lease *lease;
+
+	reply = (struct dhcp_message *) l_new(uint8_t, len);
+
+	server_message_init(server, client_msg, reply);
+
+	_dhcp_message_builder_init(&builder, reply, len, DHCP_MESSAGE_TYPE_ACK);
+
+	reply->yiaddr = dest;
+
+	_dhcp_message_builder_append(&builder,
+					L_DHCP_OPTION_IP_ADDRESS_LEASE_TIME,
+					4, &lease_time);
+
+	add_server_options(server, &builder);
+
+	_dhcp_message_builder_append(&builder, L_DHCP_OPTION_SERVER_IDENTIFIER,
+					4, &server->address);
+
+	_dhcp_message_builder_finalize(&builder, &len);
+
+	SERVER_DEBUG("Sending ACK to %s", IP_STR(reply->yiaddr));
+
+	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 ACK");
+		return;
+	}
+
+	lease = add_lease(server, 0, reply->chaddr, reply->yiaddr);
+
+	if (server->event_handler)
+		server->event_handler(server, L_DHCP_SERVER_EVENT_NEW_LEASE,
+					server->user_data, lease);
+}
+
 static void listener_event(const void *data, size_t len, void *user_data)
 {
 	struct l_dhcp_server *server = user_data;
@@ -412,6 +483,26 @@ static void listener_event(const void *data, size_t len, void *user_data)
 
 		send_offer(server, message, lease, requested_ip_opt);
 
+		break;
+	case DHCP_MESSAGE_TYPE_REQUEST:
+		SERVER_DEBUG("Received REQUEST, requested IP %s",
+				IP_STR(requested_ip_opt));
+
+		if (requested_ip_opt == 0) {
+			requested_ip_opt = message->ciaddr;
+			if (requested_ip_opt == 0)
+				break;
+		}
+
+		if (lease && requested_ip_opt == lease->address) {
+			send_ack(server, message, lease->address);
+			break;
+		}
+
+		if (server_id_opt || !lease) {
+			send_nak(server, message);
+			break;
+		}
 		break;
 	}
 }
-- 
2.26.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v7 3/6] dhcp-server: handle DECLINE messages
  2020-10-20 15:52 [PATCH v7 1/6] dhcp-server: process DISCOVER and send OFFER James Prestwood
  2020-10-20 15:52 ` [PATCH v7 2/6] dhcp-server: add REQUEST processing James Prestwood
@ 2020-10-20 15:52 ` James Prestwood
  2020-10-20 16:33   ` Denis Kenzior
  2020-10-20 15:52 ` [PATCH v7 4/6] dhcp-server: add RELEASE message support James Prestwood
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 7+ messages in thread
From: James Prestwood @ 2020-10-20 15:52 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 1354 bytes --]

Process DECLINE messages from clients and remove any pending
leases that were created during DISCOVER.
---
 ell/dhcp-server.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

v7:
 * Removed event from remove_lease since this is only called due to
   a DECLINE message and no NEW_LEASE event would have been called.

diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index 2008c56..5fe68fd 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -111,6 +111,14 @@ static struct l_dhcp_lease *find_lease_by_mac(struct l_dhcp_server *server,
 	return l_queue_find(server->lease_list, match_lease_mac, mac);
 }
 
+static void remove_lease(struct l_dhcp_server *server,
+				struct l_dhcp_lease *lease)
+{
+	l_queue_remove(server->lease_list, lease);
+
+	_dhcp_lease_free(lease);
+}
+
 /* 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,
@@ -504,6 +512,16 @@ static void listener_event(const void *data, size_t len, void *user_data)
 			break;
 		}
 		break;
+	case DHCP_MESSAGE_TYPE_DECLINE:
+		SERVER_DEBUG("Received DECLINE");
+
+		if (!server_id_opt || !requested_ip_opt || !lease)
+			break;
+
+		if (requested_ip_opt == lease->address)
+			remove_lease(server, lease);
+
+		break;
 	}
 }
 
-- 
2.26.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v7 4/6] dhcp-server: add RELEASE message support
  2020-10-20 15:52 [PATCH v7 1/6] dhcp-server: process DISCOVER and send OFFER James Prestwood
  2020-10-20 15:52 ` [PATCH v7 2/6] dhcp-server: add REQUEST processing James Prestwood
  2020-10-20 15:52 ` [PATCH v7 3/6] dhcp-server: handle DECLINE messages James Prestwood
@ 2020-10-20 15:52 ` James Prestwood
  2020-10-20 15:52 ` [PATCH v7 5/6] dhcp-server: add INFORM message handling James Prestwood
  2020-10-20 15:52 ` [PATCH v7 6/6] unit: add complete client/server dhcp test James Prestwood
  4 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2020-10-20 15:52 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 1608 bytes --]

Handle RELEASE messages from clients. If there is a valid lease
set the expire time to now which releases the IP but also allows
the client to reconnect and maintain the same IP so long as
it hadn't been leased out again.
---
 ell/dhcp-server.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

v7:
 * Renamed lease_set_expire to lease_release

diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index 5fe68fd..777265d 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -195,6 +195,20 @@ static struct l_dhcp_lease *add_lease(struct l_dhcp_server *server,
 	return lease;
 }
 
+static void lease_release(struct l_dhcp_server *server,
+			struct l_dhcp_lease *lease, uint32_t expire)
+{
+	l_queue_remove(server->lease_list, lease);
+
+	lease->lifetime = expire;
+
+	l_queue_insert(server->lease_list, lease, compare_lifetime, NULL);
+
+	if (server->event_handler)
+		server->event_handler(server, L_DHCP_SERVER_EVENT_LEASE_EXPIRED,
+					server->user_data, lease);
+}
+
 static bool match_lease_ip(const void *data, const void *user_data)
 {
 	const struct l_dhcp_lease *lease = data;
@@ -521,6 +535,17 @@ static void listener_event(const void *data, size_t len, void *user_data)
 		if (requested_ip_opt == lease->address)
 			remove_lease(server, lease);
 
+		break;
+	case DHCP_MESSAGE_TYPE_RELEASE:
+		SERVER_DEBUG("Received RELEASE");
+
+		if (!server_id_opt || !lease)
+			break;
+
+		if (message->ciaddr == lease->address)
+			lease_release(server, lease,
+						l_time_to_secs(l_time_now()));
+
 		break;
 	}
 }
-- 
2.26.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v7 5/6] dhcp-server: add INFORM message handling
  2020-10-20 15:52 [PATCH v7 1/6] dhcp-server: process DISCOVER and send OFFER James Prestwood
                   ` (2 preceding siblings ...)
  2020-10-20 15:52 ` [PATCH v7 4/6] dhcp-server: add RELEASE message support James Prestwood
@ 2020-10-20 15:52 ` James Prestwood
  2020-10-20 15:52 ` [PATCH v7 6/6] unit: add complete client/server dhcp test James Prestwood
  4 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2020-10-20 15:52 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 1625 bytes --]

This allows clients to request local configuration details
if their IP is already configured.
---
 ell/dhcp-server.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index 777265d..4a7e8e3 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -383,6 +383,30 @@ static void send_offer(struct l_dhcp_server *server,
 		SERVER_DEBUG("Failed to send OFFER");
 }
 
+static void send_inform(struct l_dhcp_server *server,
+				const struct dhcp_message *client_msg)
+{
+	struct dhcp_message_builder builder;
+	size_t len = sizeof(struct dhcp_message) + DHCP_MIN_OPTIONS_SIZE;
+	L_AUTO_FREE_VAR(struct dhcp_message *, reply);
+
+	reply = (struct dhcp_message *) l_new(uint8_t, len);
+
+	server_message_init(server, client_msg, reply);
+
+	_dhcp_message_builder_init(&builder, reply, len, DHCP_MESSAGE_TYPE_ACK);
+
+	add_server_options(server, &builder);
+
+	_dhcp_message_builder_finalize(&builder, &len);
+
+	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 INFORM");
+}
+
 static void send_nak(struct l_dhcp_server *server,
 			const struct dhcp_message *client_msg)
 {
@@ -547,6 +571,11 @@ static void listener_event(const void *data, size_t len, void *user_data)
 						l_time_to_secs(l_time_now()));
 
 		break;
+	case DHCP_MESSAGE_TYPE_INFORM:
+		SERVER_DEBUG("Received INFORM");
+
+		send_inform(server, message);
+		break;
 	}
 }
 
-- 
2.26.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v7 6/6] unit: add complete client/server dhcp test
  2020-10-20 15:52 [PATCH v7 1/6] dhcp-server: process DISCOVER and send OFFER James Prestwood
                   ` (3 preceding siblings ...)
  2020-10-20 15:52 ` [PATCH v7 5/6] dhcp-server: add INFORM message handling James Prestwood
@ 2020-10-20 15:52 ` James Prestwood
  4 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2020-10-20 15:52 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 6776 bytes --]

---
 unit/test-dhcp.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 191 insertions(+)

diff --git a/unit/test-dhcp.c b/unit/test-dhcp.c
index 0a7208d..877d649 100644
--- a/unit/test-dhcp.c
+++ b/unit/test-dhcp.c
@@ -36,6 +36,8 @@
 static bool verbose = false;
 static uint8_t client_packet[1024];
 static size_t client_packet_len;
+static uint8_t server_packet[1024];
+static size_t server_packet_len;
 
 static void test_request_option(const void *data)
 {
@@ -736,6 +738,193 @@ static void test_discover(const void *data)
 	l_dhcp_client_destroy(client);
 }
 
+static bool l2_send_called = false;
+
+static int fake_transport_server_l2_send(struct dhcp_transport *s,
+					uint32_t source_ip,
+					uint16_t source_port,
+					uint32_t dest_ip,
+					uint16_t dest_port,
+					const uint8_t *dest_arp,
+					const void *data, size_t len)
+{
+	assert(len <= sizeof(server_packet));
+	memcpy(server_packet, data, len);
+	server_packet_len = len;
+
+	l2_send_called = true;
+
+	return 0;
+}
+
+static void do_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	l_info("%s%s", prefix, str);
+}
+
+static void test_complete_run(const void *data)
+{
+	static const uint8_t addr1[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+	static const uint8_t addr2[6] = { 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
+
+	char *dns[] = { "192.168.1.1", "192.168.1.254", NULL };
+	struct l_dhcp_client *client1;
+	struct l_dhcp_client *client2;
+	struct l_dhcp_server *server;
+	struct dhcp_transport *cli_transport1 = l_new(struct dhcp_transport, 1);
+	struct dhcp_transport *cli_transport2 = l_new(struct dhcp_transport, 1);
+
+	struct dhcp_transport *srv_transport = l_new(struct dhcp_transport, 1);
+	const struct l_dhcp_lease *cli_lease;
+	/* client IP address */
+	char *cli_addr;
+	/* servers IP address */
+	char *srv_addr;
+	char *tmp_addr;
+	char **dns_list;
+
+	server = l_dhcp_server_new(41);
+
+	assert(l_dhcp_server_set_interface_name(server, "fake"));
+	assert(l_dhcp_server_set_ip_address(server, "192.168.1.1"));
+	assert(l_dhcp_server_set_ip_range(server, "192.168.1.2",
+						"192.168.1.100"));
+	assert(l_dhcp_server_set_netmask(server, "255.255.255.0"));
+	assert(l_dhcp_server_set_gateway(server, "192.168.1.1"));
+	assert(l_dhcp_server_set_dns(server, dns));
+
+	if (verbose)
+		l_dhcp_server_set_debug(server, do_debug, "[DHCP SERV] ", NULL);
+
+	srv_transport->ifindex = 41;
+	srv_transport->l2_send = fake_transport_server_l2_send;
+
+	assert(_dhcp_server_set_transport(server, srv_transport));
+
+	assert(l_dhcp_server_start(server));
+
+	client1 = l_dhcp_client_new(42);
+
+	assert(l_dhcp_client_set_address(client1, ARPHRD_ETHER, addr1, 6));
+	assert(l_dhcp_client_set_interface_name(client1, "fake"));
+	assert(l_dhcp_client_set_hostname(client1, "<hostname>"));
+	_dhcp_client_override_xid(client1, 0x4d7c67c6);
+	assert(l_dhcp_client_set_event_handler(client1,
+				event_handler_lease_obtained, NULL, NULL));
+
+	if (verbose)
+		l_dhcp_client_set_debug(client1, do_debug, "[DHCP1] ", NULL);
+
+	cli_transport1->send = fake_transport_send;
+	cli_transport1->l2_send = fake_transport_l2_send;
+	cli_transport1->ifindex = 42;
+
+	assert(_dhcp_client_set_transport(client1, cli_transport1));
+
+	assert(l_dhcp_client_start(client1));
+
+	client2 = l_dhcp_client_new(43);
+	assert(l_dhcp_client_set_address(client2, ARPHRD_ETHER, addr2, 6));
+	assert(l_dhcp_client_set_interface_name(client2, "fake"));
+	assert(l_dhcp_client_set_hostname(client2, "<hostname>"));
+	_dhcp_client_override_xid(client2, 0x5d7c67c6);
+	assert(l_dhcp_client_set_event_handler(client2,
+				event_handler_lease_obtained, NULL, NULL));
+
+	if (verbose)
+		l_dhcp_client_set_debug(client2, do_debug, "[DHCP2] ", NULL);
+
+	cli_transport2->send = fake_transport_send;
+	cli_transport2->l2_send = fake_transport_l2_send;
+	cli_transport2->ifindex = 42;
+
+	assert(_dhcp_client_set_transport(client2, cli_transport2));
+
+	/* RX DISCOVER */
+	srv_transport->rx_cb(client_packet, client_packet_len, server);
+	assert(l2_send_called);
+	l2_send_called = false;
+
+	/* RX OFFER */
+	cli_transport1->rx_cb(server_packet, server_packet_len, client1);
+
+	/* RX REQUEST */
+	srv_transport->rx_cb(client_packet, client_packet_len, server);
+	assert(l2_send_called);
+	l2_send_called = false;
+
+	/* RX ACK */
+	cli_transport1->rx_cb(server_packet, server_packet_len, client1);
+
+	assert(event_handler_called);
+
+	cli_lease = l_dhcp_client_get_lease(client1);
+	assert(cli_lease);
+	cli_addr = l_dhcp_lease_get_address(cli_lease);
+	assert(cli_addr);
+	assert(!strcmp(cli_addr, "192.168.1.2"));
+	srv_addr = l_dhcp_lease_get_server_id(cli_lease);
+	assert(!strcmp(srv_addr, "192.168.1.1"));
+	l_free(srv_addr);
+	l_free(cli_addr);
+
+	tmp_addr = l_dhcp_lease_get_gateway(cli_lease);
+	assert(!strcmp(tmp_addr, "192.168.1.1"));
+	l_free(tmp_addr);
+
+	tmp_addr = l_dhcp_lease_get_netmask(cli_lease);
+	assert(!strcmp(tmp_addr, "255.255.255.0"));
+	l_free(tmp_addr);
+
+	dns_list = l_dhcp_lease_get_dns(cli_lease);
+	assert(dns_list && dns_list[0] && dns_list[1]);
+	assert(!strcmp(dns_list[0], "192.168.1.1"));
+	assert(!strcmp(dns_list[1], "192.168.1.254"));
+	l_strv_free(dns_list);
+
+	/* Second client connect */
+	assert(l_dhcp_client_start(client2));
+
+	/* RX DISCOVER */
+	srv_transport->rx_cb(client_packet, client_packet_len, server);
+	assert(l2_send_called);
+	l2_send_called = false;
+
+	/* RX OFFER */
+	cli_transport2->rx_cb(server_packet, server_packet_len, client2);
+
+	/* RX REQUEST */
+	srv_transport->rx_cb(client_packet, client_packet_len, server);
+	assert(l2_send_called);
+	l2_send_called = false;
+
+	/* RX ACK */
+	cli_transport2->rx_cb(server_packet, server_packet_len, client2);
+
+	assert(event_handler_called);
+
+	cli_lease = l_dhcp_client_get_lease(client2);
+	assert(cli_lease);
+	cli_addr = l_dhcp_lease_get_address(cli_lease);
+	assert(cli_addr);
+	assert(!strcmp(cli_addr, "192.168.1.3"));
+	srv_addr = l_dhcp_lease_get_server_id(cli_lease);
+	assert(!strcmp(srv_addr, "192.168.1.1"));
+	l_free(srv_addr);
+	l_free(cli_addr);
+
+
+	l_dhcp_client_stop(client1);
+	l_dhcp_client_stop(client2);
+	l_dhcp_client_destroy(client1);
+	l_dhcp_client_destroy(client2);
+
+	l_dhcp_server_stop(server);
+	l_dhcp_server_destroy(server);
+}
+
 int main(int argc, char *argv[])
 {
 	l_test_init(&argc, &argv);
@@ -759,5 +948,7 @@ int main(int argc, char *argv[])
 
 	l_test_add("discover", test_discover, NULL);
 
+	l_test_add("complete run", test_complete_run, NULL);
+
 	return l_test_run();
 }
-- 
2.26.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v7 3/6] dhcp-server: handle DECLINE messages
  2020-10-20 15:52 ` [PATCH v7 3/6] dhcp-server: handle DECLINE messages James Prestwood
@ 2020-10-20 16:33   ` Denis Kenzior
  0 siblings, 0 replies; 7+ messages in thread
From: Denis Kenzior @ 2020-10-20 16:33 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 497 bytes --]

Hi James,

On 10/20/20 10:52 AM, James Prestwood wrote:
> Process DECLINE messages from clients and remove any pending
> leases that were created during DISCOVER.
> ---
>   ell/dhcp-server.c | 18 ++++++++++++++++++
>   1 file changed, 18 insertions(+)
> 
> v7:
>   * Removed event from remove_lease since this is only called due to
>     a DECLINE message and no NEW_LEASE event would have been called.
> 

Patch 3-5 applied, thanks.  Rest were applied from v6.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-10-20 16:33 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-20 15:52 [PATCH v7 1/6] dhcp-server: process DISCOVER and send OFFER James Prestwood
2020-10-20 15:52 ` [PATCH v7 2/6] dhcp-server: add REQUEST processing James Prestwood
2020-10-20 15:52 ` [PATCH v7 3/6] dhcp-server: handle DECLINE messages James Prestwood
2020-10-20 16:33   ` Denis Kenzior
2020-10-20 15:52 ` [PATCH v7 4/6] dhcp-server: add RELEASE message support James Prestwood
2020-10-20 15:52 ` [PATCH v7 5/6] dhcp-server: add INFORM message handling James Prestwood
2020-10-20 15:52 ` [PATCH v7 6/6] unit: add complete client/server dhcp test James Prestwood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.