All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/20] net: add l_net_get_address()
@ 2020-10-16 15:36 James Prestwood
  2020-10-16 15:36 ` [PATCH 02/20] dhcp-util: add dhcp message builder APIs James Prestwood
                   ` (18 more replies)
  0 siblings, 19 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

---
 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

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

* [PATCH 02/20] dhcp-util: add dhcp message builder APIs
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 03/20] dhcp: update client code to use " James Prestwood
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

A new file was added, dhcp-util.c. Some enums/constant values
were moved from dhcp.c into dhcp-private.h for use with the
new builder APIs.
---
 Makefile.am        |   1 +
 ell/dhcp-private.h |  33 ++++++++++
 ell/dhcp-util.c    | 160 +++++++++++++++++++++++++++++++++++++++++++++
 ell/dhcp.c         |  16 -----
 4 files changed, 194 insertions(+), 16 deletions(-)
 create mode 100644 ell/dhcp-util.c

diff --git a/Makefile.am b/Makefile.am
index 9b3e3c9..beba535 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -127,6 +127,7 @@ ell_libell_la_SOURCES = $(linux_headers) \
 			ell/dhcp6.c \
 			ell/dhcp6-transport.c \
 			ell/dhcp6-lease.c \
+			ell/dhcp-util.c \
 			ell/cert.c \
 			ell/cert-private.h \
 			ell/ecc-private.h \
diff --git a/ell/dhcp-private.h b/ell/dhcp-private.h
index a75bb8b..3aa89fb 100644
--- a/ell/dhcp-private.h
+++ b/ell/dhcp-private.h
@@ -27,6 +27,17 @@ enum {
 	DHCP_PORT_CLIENT = 68,
 };
 
+enum dhcp_message_type {
+	DHCP_MESSAGE_TYPE_DISCOVER = 1,
+	DHCP_MESSAGE_TYPE_OFFER = 2,
+	DHCP_MESSAGE_TYPE_REQUEST = 3,
+	DHCP_MESSAGE_TYPE_DECLINE = 4,
+	DHCP_MESSAGE_TYPE_ACK = 5,
+	DHCP_MESSAGE_TYPE_NAK = 6,
+	DHCP_MESSAGE_TYPE_RELEASE = 7,
+	DHCP_MESSAGE_TYPE_INFORM = 8,
+};
+
 /* RFC 2131, Table 1 */
 enum dhcp_op_code {
 	DHCP_OP_CODE_BOOTREQUEST = 1,
@@ -35,6 +46,11 @@ enum dhcp_op_code {
 
 #define DHCP_MAGIC 0x63825363
 
+/* RFC 2132, Section 9.6. DHCP Message Type */
+#define DHCP_OPTION_MESSAGE_TYPE 53
+#define DHCP_OPTION_PAD 0 /* RFC 2132, Section 3.1 */
+#define DHCP_OPTION_END 255 /* RFC 2132, Section 3.2 */
+
 /* RFC 2131, Figure 1 */
 struct dhcp_message {
 	uint8_t op;
@@ -126,3 +142,20 @@ struct l_dhcp_lease {
 struct l_dhcp_lease *_dhcp_lease_new(void);
 void _dhcp_lease_free(struct l_dhcp_lease *lease);
 struct l_dhcp_lease *_dhcp_lease_parse_options(struct dhcp_message_iter *iter);
+
+struct dhcp_message_builder {
+	unsigned int max;
+	uint8_t *pos;
+	uint8_t *start;
+};
+
+bool _dhcp_message_builder_init(struct dhcp_message_builder *builder,
+				struct dhcp_message *message,
+				size_t len, uint8_t type);
+bool _dhcp_message_builder_append(struct dhcp_message_builder *builder,
+					uint8_t code, size_t optlen,
+					const void *optval);
+bool _dhcp_message_builder_append_prl(struct dhcp_message_builder *builder,
+					const unsigned long *reqopts);
+uint8_t *_dhcp_message_builder_finalize(struct dhcp_message_builder *builder,
+					size_t *outlen);
diff --git a/ell/dhcp-util.c b/ell/dhcp-util.c
new file mode 100644
index 0000000..e02fab0
--- /dev/null
+++ b/ell/dhcp-util.c
@@ -0,0 +1,160 @@
+/*
+ *
+ *  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
+ *
+ */
+#include <stdint.h>
+#include <linux/types.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "dhcp-private.h"
+#include "private.h"
+
+#define BITS_PER_LONG (sizeof(unsigned long) * 8)
+
+static void dhcp_init_header(struct dhcp_message *message, uint8_t type)
+{
+	switch (type) {
+	case DHCP_MESSAGE_TYPE_OFFER:
+	case DHCP_MESSAGE_TYPE_NAK:
+	case DHCP_MESSAGE_TYPE_ACK:
+		message->op = DHCP_OP_CODE_BOOTREPLY;
+		break;
+	default:
+		message->op = DHCP_OP_CODE_BOOTREQUEST;
+		break;
+	}
+
+	message->htype = 1;
+	message->hlen = 6;
+	message->magic = htonl(DHCP_MAGIC);
+	message->options[0] = DHCP_OPTION_END;
+}
+
+#define LEN_CHECK(builder, next) \
+	if ((builder)->pos - (builder)->start + (next) > (builder)->max) \
+		return false;
+
+bool _dhcp_message_builder_append(struct dhcp_message_builder *builder,
+					uint8_t code, size_t optlen,
+					const void *optval)
+{
+	switch (code) {
+	case DHCP_OPTION_PAD:
+	case DHCP_OPTION_END:
+		LEN_CHECK(builder, 1);
+
+		builder->pos[0] = code;
+		builder->pos += 1;
+		break;
+	default:
+		LEN_CHECK(builder, optlen + 2);
+
+		builder->pos[0] = code;
+		builder->pos[1] = optlen;
+		memcpy(builder->pos + 2, optval, optlen);
+
+		builder->pos += optlen + 2;
+		break;
+	}
+
+	return true;
+}
+
+bool _dhcp_message_builder_append_prl(struct dhcp_message_builder *builder,
+					const unsigned long *reqopts)
+{
+	uint8_t optlen = 0;
+	unsigned int i;
+	unsigned int j;
+
+	for (i = 0; i < 256 / BITS_PER_LONG; i++)
+		optlen += __builtin_popcountl(reqopts[i]);
+
+	/*
+	 * This function assumes that there's enough space to put the PRL
+	 * into the buffer without resorting to file or sname overloading
+	 */
+	LEN_CHECK(builder, optlen + 2U);
+
+	i = 0;
+	builder->pos[i++] = DHCP_OPTION_PARAMETER_REQUEST_LIST;
+	builder->pos[i++] = optlen;
+
+	for (j = 0; j < 256; j++) {
+		if (reqopts[j / BITS_PER_LONG] & 1UL << (j % BITS_PER_LONG)) {
+			builder->pos[i++] = j;
+		}
+	}
+
+	builder->pos += optlen + 2;
+
+	return true;
+}
+
+bool _dhcp_message_builder_init(struct dhcp_message_builder *builder,
+				struct dhcp_message *message,
+				size_t len, uint8_t type)
+{
+	if (!builder || !message || !len)
+		return false;
+
+	builder->max = len;
+	builder->pos = (uint8_t *) message->options;
+	builder->start = (uint8_t *) message;
+
+	dhcp_init_header(message, type);
+
+	return _dhcp_message_builder_append(builder, DHCP_OPTION_MESSAGE_TYPE,
+						1, &type);
+}
+
+static inline int dhcp_message_optimize(struct dhcp_message *message,
+					const uint8_t *end)
+{
+	/*
+	 * Don't bother sending a full sized dhcp_message as it is most likely
+	 * mostly zeros.  Instead truncate it at DHCP_OPTION_END and align to
+	 * the nearest 4 byte boundary.  Many implementations expect a packet
+	 * of a certain size or it is filtered, so we cap the length in
+	 * accordance to RFC 1542:
+	 * "The IP Total Length and UDP Length must be large enough to contain
+	 * the minimal BOOTP header of 300 octets"
+	 */
+	size_t len = align_len(end - (uint8_t *) message, 4);
+	if (len < 300)
+		len = 300;
+
+	return len;
+}
+
+uint8_t *_dhcp_message_builder_finalize(struct dhcp_message_builder *builder,
+					size_t *outlen)
+{
+	_dhcp_message_builder_append(builder, DHCP_OPTION_END, 0, NULL);
+
+	*outlen = dhcp_message_optimize((struct dhcp_message *)builder->start,
+				builder->pos);
+
+	return builder->start;
+}
diff --git a/ell/dhcp.c b/ell/dhcp.c
index fd548b5..097bf3d 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -50,9 +50,6 @@
 
 #define BITS_PER_LONG (sizeof(unsigned long) * 8)
 
-#define DHCP_OPTION_PAD 0 /* RFC 2132, Section 3.1 */
-#define DHCP_OPTION_END 255 /* RFC 2132, Section 3.2 */
-
 /* RFC 2132, Section 9.3. Option Overload */
 #define DHCP_OPTION_OVERLOAD 52
 enum dhcp_option_overload {
@@ -61,19 +58,6 @@ enum dhcp_option_overload {
 	DHCP_OVERLOAD_BOTH = 3,
 };
 
-/* RFC 2132, Section 9.6. DHCP Message Type */
-#define DHCP_OPTION_MESSAGE_TYPE 53
-enum dhcp_message_type {
-	DHCP_MESSAGE_TYPE_DISCOVER = 1,
-	DHCP_MESSAGE_TYPE_OFFER = 2,
-	DHCP_MESSAGE_TYPE_REQUEST = 3,
-	DHCP_MESSAGE_TYPE_DECLINE = 4,
-	DHCP_MESSAGE_TYPE_ACK = 5,
-	DHCP_MESSAGE_TYPE_NAK = 6,
-	DHCP_MESSAGE_TYPE_RELEASE = 7,
-	DHCP_MESSAGE_TYPE_INFORM = 8,
-};
-
 #define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* Section 9.8 */
 #define DHCP_OPTION_MAXIMUM_MESSAGE_SIZE 57 /* Section 9.10 */
 #define DHCP_OPTION_CLIENT_IDENTIFIER 61 /* Section 9.14 */
-- 
2.26.2

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

* [PATCH 03/20] dhcp: update client code to use builder APIs
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
  2020-10-16 15:36 ` [PATCH 02/20] dhcp-util: add dhcp message builder APIs James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 04/20] dhcp-util: move iter APIs to dhcp-util James Prestwood
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

---
 ell/dhcp.c | 148 ++++++++++++++++-------------------------------------
 1 file changed, 43 insertions(+), 105 deletions(-)

diff --git a/ell/dhcp.c b/ell/dhcp.c
index 097bf3d..2541637 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -301,61 +301,6 @@ int _dhcp_option_append(uint8_t **buf, size_t *buflen, uint8_t code,
 	return 0;
 }
 
-static int dhcp_append_prl(const unsigned long *reqopts,
-					uint8_t **buf, size_t *buflen)
-{
-	uint8_t optlen = 0;
-	unsigned int i;
-	unsigned int j;
-
-	if (!buf || !buflen)
-		return -EINVAL;
-
-	for (i = 0; i < 256 / BITS_PER_LONG; i++)
-		optlen += __builtin_popcountl(reqopts[i]);
-
-	/*
-	 * This function assumes that there's enough space to put the PRL
-	 * into the buffer without resorting to file or sname overloading
-	 */
-	if (*buflen < optlen + 2U)
-		return -ENOBUFS;
-
-	i = 0;
-	(*buf)[i++] = DHCP_OPTION_PARAMETER_REQUEST_LIST;
-	(*buf)[i++] = optlen;
-
-	for (j = 0; j < 256; j++) {
-		if (reqopts[j / BITS_PER_LONG] & 1UL << (j % BITS_PER_LONG))
-			(*buf)[i++] = j;
-	}
-
-	*buf += optlen + 2;
-	*buflen -= (optlen + 2);
-
-	return 0;
-}
-
-static int dhcp_message_init(struct dhcp_message *message,
-				enum dhcp_op_code op,
-				uint8_t type, uint32_t xid,
-				uint8_t **opt, size_t *optlen)
-{
-	int err;
-
-	message->op = op;
-	message->xid = L_CPU_TO_BE32(xid);
-	message->magic = L_CPU_TO_BE32(DHCP_MAGIC);
-	*opt = (uint8_t *)(message + 1);
-
-	err = _dhcp_option_append(opt, optlen,
-					DHCP_OPTION_MESSAGE_TYPE, 1, &type);
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
 static void dhcp_message_set_address_type(struct dhcp_message *message,
 						uint8_t addr_type,
 						uint8_t addr_len)
@@ -504,16 +449,13 @@ static uint32_t dhcp_rebind_renew_retry_time(uint64_t start_t, uint32_t expiry)
 
 static int client_message_init(struct l_dhcp_client *client,
 					struct dhcp_message *message,
-					uint8_t type,
-					uint8_t **opt, size_t *optlen)
+					struct dhcp_message_builder *builder)
 {
-	int err;
 	uint16_t max_size;
 
-	err = dhcp_message_init(message, DHCP_OP_CODE_BOOTREQUEST,
-				type, client->xid, opt, optlen);
-	if (err < 0)
-		return err;
+	message->op = DHCP_OP_CODE_BOOTREQUEST;
+	message->xid = L_CPU_TO_BE32(client->xid);
+	message->magic = L_CPU_TO_BE32(DHCP_MAGIC);
 
 	dhcp_message_set_address_type(message, client->addr_type,
 							client->addr_len);
@@ -534,20 +476,19 @@ static int client_message_init(struct l_dhcp_client *client,
 	 */
 	message->secs = L_CPU_TO_BE16(dhcp_attempt_secs(client->start_t));
 
-	err = dhcp_append_prl(client->request_options, opt, optlen);
-	if (err < 0)
-		return err;
+	if (!_dhcp_message_builder_append_prl(builder,
+						client->request_options))
+		return -EINVAL;
 
 	/*
 	 * Set the maximum DHCP message size to the minimum legal value.  This
 	 * helps some buggy DHCP servers to not send bigger packets
 	 */
 	max_size = L_CPU_TO_BE16(576);
-	err = _dhcp_option_append(opt, optlen,
+	if (!_dhcp_message_builder_append(builder,
 					DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
-					2, &max_size);
-	if (err < 0)
-		return err;
+					2, &max_size))
+		return -EINVAL;
 
 	return 0;
 }
@@ -561,7 +502,7 @@ static void dhcp_client_event_notify(struct l_dhcp_client *client,
 
 static int dhcp_client_send_discover(struct l_dhcp_client *client)
 {
-	uint8_t *opt;
+	struct dhcp_message_builder builder;
 	size_t optlen = DHCP_MIN_OPTIONS_SIZE;
 	size_t len = sizeof(struct dhcp_message) + optlen;
 	L_AUTO_FREE_VAR(struct dhcp_message *, discover);
@@ -571,26 +512,21 @@ static int dhcp_client_send_discover(struct l_dhcp_client *client)
 
 	discover = (struct dhcp_message *) l_new(uint8_t, len);
 
-	err = client_message_init(client, discover,
-					DHCP_MESSAGE_TYPE_DISCOVER,
-					&opt, &optlen);
+	_dhcp_message_builder_init(&builder, discover, len,
+					DHCP_MESSAGE_TYPE_DISCOVER);
+
+	err = client_message_init(client, discover, &builder);
 	if (err < 0)
 		return err;
 
-	if (client->hostname) {
-		err = _dhcp_option_append(&opt, &optlen,
+	if (client->hostname)
+		if (!_dhcp_message_builder_append(&builder,
 						L_DHCP_OPTION_HOST_NAME,
 						strlen(client->hostname),
-						client->hostname);
-		if (err < 0)
-			return err;
-	}
-
-	err = _dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
-	if (err < 0)
-		return err;
+						client->hostname))
+			return -EINVAL;
 
-	len = dhcp_message_optimize(discover, opt);
+	_dhcp_message_builder_finalize(&builder, &len);
 
 	return client->transport->broadcast(client->transport,
 					INADDR_ANY, DHCP_PORT_CLIENT,
@@ -600,7 +536,7 @@ static int dhcp_client_send_discover(struct l_dhcp_client *client)
 
 static int dhcp_client_send_request(struct l_dhcp_client *client)
 {
-	uint8_t *opt;
+	struct dhcp_message_builder builder;
 	size_t optlen = DHCP_MIN_OPTIONS_SIZE;
 	size_t len = sizeof(struct dhcp_message) + optlen;
 	L_AUTO_FREE_VAR(struct dhcp_message *, request);
@@ -610,9 +546,11 @@ static int dhcp_client_send_request(struct l_dhcp_client *client)
 
 	request = (struct dhcp_message *) l_new(uint8_t, len);
 
-	err = client_message_init(client, request,
-					DHCP_MESSAGE_TYPE_REQUEST,
-					&opt, &optlen);
+	_dhcp_message_builder_init(&builder, request, len,
+					DHCP_MESSAGE_TYPE_REQUEST);
+
+
+	err = client_message_init(client, request, &builder);
 	if (err < 0)
 		return err;
 
@@ -633,17 +571,20 @@ static int dhcp_client_send_request(struct l_dhcp_client *client)
 		 *
 		 * NOTE: 'SELECTING' is meant to be 'REQUESTING' in the RFC
 		 */
-		err = _dhcp_option_append(&opt, &optlen,
+		if (!_dhcp_message_builder_append(&builder,
 					L_DHCP_OPTION_SERVER_IDENTIFIER,
-					4, &client->lease->server_address);
-		if (err < 0)
-			return err;
+					4, &client->lease->server_address)) {
+			CLIENT_DEBUG("Failed to append server ID");
+			return -EINVAL;
+		}
 
-		err = _dhcp_option_append(&opt, &optlen,
+		if (!_dhcp_message_builder_append(&builder,
 					L_DHCP_OPTION_REQUESTED_IP_ADDRESS,
-					4, &client->lease->address);
-		if (err < 0)
-			return err;
+					4, &client->lease->address)) {
+			CLIENT_DEBUG("Failed to append requested IP");
+			return -EINVAL;
+		}
+
 		break;
 	case DHCP_STATE_RENEWING:
 	case DHCP_STATE_REBINDING:
@@ -659,19 +600,16 @@ static int dhcp_client_send_request(struct l_dhcp_client *client)
 	}
 
 	if (client->hostname) {
-		err = _dhcp_option_append(&opt, &optlen,
+		if (!_dhcp_message_builder_append(&builder,
 						L_DHCP_OPTION_HOST_NAME,
 						strlen(client->hostname),
-						client->hostname);
-		if (err < 0)
-			return err;
+						client->hostname)) {
+			CLIENT_DEBUG("Failed to append host name");
+			return -EINVAL;
+		}
 	}
 
-	err = _dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
-	if (err < 0)
-		return err;
-
-	len = dhcp_message_optimize(request, opt);
+	_dhcp_message_builder_finalize(&builder, &len);
 
 	/*
 	 * RFC2131, Section 4.1:
-- 
2.26.2

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

* [PATCH 04/20] dhcp-util: move iter APIs to dhcp-util
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
  2020-10-16 15:36 ` [PATCH 02/20] dhcp-util: add dhcp message builder APIs James Prestwood
  2020-10-16 15:36 ` [PATCH 03/20] dhcp: update client code to use " James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 16:24   ` Denis Kenzior
  2020-10-16 15:36 ` [PATCH 05/20] dhcp-transport: modify BPF filter for server James Prestwood
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

These were already exposed for use elsewhere but dhcp-util
is a better home for these APIs.
---
 ell/dhcp-util.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++
 ell/dhcp.c      | 160 ------------------------------------------------
 2 files changed, 160 insertions(+), 160 deletions(-)

diff --git a/ell/dhcp-util.c b/ell/dhcp-util.c
index e02fab0..7809e52 100644
--- a/ell/dhcp-util.c
+++ b/ell/dhcp-util.c
@@ -158,3 +158,163 @@ uint8_t *_dhcp_message_builder_finalize(struct dhcp_message_builder *builder,
 
 	return builder->start;
 }
+
+bool _dhcp_message_iter_init(struct dhcp_message_iter *iter,
+				const struct dhcp_message *message, size_t len)
+{
+	if (!message)
+		return false;
+
+	if (len < sizeof(struct dhcp_message))
+		return false;
+
+	if (L_BE32_TO_CPU(message->magic) != DHCP_MAGIC)
+		return false;
+
+	memset(iter, 0, sizeof(*iter));
+	iter->message = message;
+	iter->message_len = len;
+	iter->max = len - sizeof(struct dhcp_message);
+	iter->options = message->options;
+	iter->can_overload = true;
+
+	return true;
+}
+
+static bool next_option(struct dhcp_message_iter *iter,
+				uint8_t *t, uint8_t *l, const void **v)
+{
+	uint8_t type;
+	uint8_t len;
+
+	while (iter->pos < iter->max) {
+		type = iter->options[iter->pos];
+
+		switch (type) {
+		case DHCP_OPTION_PAD:
+			iter->pos += 1;
+			continue;
+		case DHCP_OPTION_END:
+			return false;
+		default:
+			break;
+		}
+
+		if (iter->pos + 2 >= iter->max)
+			return false;
+
+		len = iter->options[iter->pos + 1];
+
+		if (iter->pos + 2 + len > iter->max)
+			return false;
+
+		*t = type;
+		*l = len;
+		*v = &iter->options[iter->pos + 2];
+
+		iter->pos += 2 + len;
+		return true;
+	}
+
+	return false;
+}
+
+bool _dhcp_message_iter_next(struct dhcp_message_iter *iter, uint8_t *type,
+				uint8_t *len, const void **data)
+{
+	bool r;
+	uint8_t t, l;
+	const void *v;
+
+	do {
+		r = next_option(iter, &t, &l, &v);
+		if (!r) {
+			iter->can_overload = false;
+
+			if (iter->overload_file) {
+				iter->options = iter->message->file;
+				iter->pos = 0;
+				iter->max = sizeof(iter->message->file);
+				iter->overload_file = false;
+				continue;
+			}
+
+			if (iter->overload_sname) {
+				iter->options = iter->message->sname;
+				iter->pos = 0;
+				iter->max = sizeof(iter->message->sname);
+				iter->overload_sname = false;
+				continue;
+			}
+
+			return r;
+		}
+
+		switch (t) {
+		case DHCP_OPTION_OVERLOAD:
+			if (l != 1)
+				continue;
+
+			if (!iter->can_overload)
+				continue;
+
+			if (l_get_u8(v) & DHCP_OVERLOAD_FILE)
+				iter->overload_file = true;
+
+			if (l_get_u8(v) & DHCP_OVERLOAD_SNAME)
+				iter->overload_sname = true;
+
+			continue;
+		default:
+			if (type)
+				*type = t;
+
+			if (len)
+				*len = l;
+
+			if (data)
+				*data = v;
+			return r;
+		}
+	} while (true);
+
+	return false;
+}
+
+int _dhcp_option_append(uint8_t **buf, size_t *buflen, uint8_t code,
+					size_t optlen, const void *optval)
+{
+	if (!buf || !buflen)
+		return -EINVAL;
+
+	switch (code) {
+
+	case DHCP_OPTION_PAD:
+	case DHCP_OPTION_END:
+		if (*buflen < 1)
+			return -ENOBUFS;
+
+		(*buf)[0] = code;
+		*buf += 1;
+		*buflen -= 1;
+		break;
+
+	default:
+		if (*buflen < optlen + 2)
+			return -ENOBUFS;
+
+		if (!optval)
+			return -EINVAL;
+
+		(*buf)[0] = code;
+		(*buf)[1] = optlen;
+		memcpy(&(*buf)[2], optval, optlen);
+
+		*buf += optlen + 2;
+		*buflen -= (optlen + 2);
+
+		break;
+	}
+
+	return 0;
+}
diff --git a/ell/dhcp.c b/ell/dhcp.c
index 2541637..e604dc0 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -141,166 +141,6 @@ const char *_dhcp_option_to_string(uint8_t option)
 	}
 }
 
-bool _dhcp_message_iter_init(struct dhcp_message_iter *iter,
-				const struct dhcp_message *message, size_t len)
-{
-	if (!message)
-		return false;
-
-	if (len < sizeof(struct dhcp_message))
-		return false;
-
-	if (L_BE32_TO_CPU(message->magic) != DHCP_MAGIC)
-		return false;
-
-	memset(iter, 0, sizeof(*iter));
-	iter->message = message;
-	iter->message_len = len;
-	iter->max = len - sizeof(struct dhcp_message);
-	iter->options = message->options;
-	iter->can_overload = true;
-
-	return true;
-}
-
-static bool next_option(struct dhcp_message_iter *iter,
-				uint8_t *t, uint8_t *l, const void **v)
-{
-	uint8_t type;
-	uint8_t len;
-
-	while (iter->pos < iter->max) {
-		type = iter->options[iter->pos];
-
-		switch (type) {
-		case DHCP_OPTION_PAD:
-			iter->pos += 1;
-			continue;
-		case DHCP_OPTION_END:
-			return false;
-		default:
-			break;
-		}
-
-		if (iter->pos + 2 >= iter->max)
-			return false;
-
-		len = iter->options[iter->pos + 1];
-
-		if (iter->pos + 2 + len > iter->max)
-			return false;
-
-		*t = type;
-		*l = len;
-		*v = &iter->options[iter->pos + 2];
-
-		iter->pos += 2 + len;
-		return true;
-	}
-
-	return false;
-}
-
-bool _dhcp_message_iter_next(struct dhcp_message_iter *iter, uint8_t *type,
-				uint8_t *len, const void **data)
-{
-	bool r;
-	uint8_t t, l;
-	const void *v;
-
-	do {
-		r = next_option(iter, &t, &l, &v);
-		if (!r) {
-			iter->can_overload = false;
-
-			if (iter->overload_file) {
-				iter->options = iter->message->file;
-				iter->pos = 0;
-				iter->max = sizeof(iter->message->file);
-				iter->overload_file = false;
-				continue;
-			}
-
-			if (iter->overload_sname) {
-				iter->options = iter->message->sname;
-				iter->pos = 0;
-				iter->max = sizeof(iter->message->sname);
-				iter->overload_sname = false;
-				continue;
-			}
-
-			return r;
-		}
-
-		switch (t) {
-		case DHCP_OPTION_OVERLOAD:
-			if (l != 1)
-				continue;
-
-			if (!iter->can_overload)
-				continue;
-
-			if (l_get_u8(v) & DHCP_OVERLOAD_FILE)
-				iter->overload_file = true;
-
-			if (l_get_u8(v) & DHCP_OVERLOAD_SNAME)
-				iter->overload_sname = true;
-
-			continue;
-		default:
-			if (type)
-				*type = t;
-
-			if (len)
-				*len = l;
-
-			if (data)
-				*data = v;
-			return r;
-		}
-	} while (true);
-
-	return false;
-}
-
-int _dhcp_option_append(uint8_t **buf, size_t *buflen, uint8_t code,
-					size_t optlen, const void *optval)
-{
-	if (!buf || !buflen)
-		return -EINVAL;
-
-	switch (code) {
-
-	case DHCP_OPTION_PAD:
-	case DHCP_OPTION_END:
-		if (*buflen < 1)
-			return -ENOBUFS;
-
-		(*buf)[0] = code;
-		*buf += 1;
-		*buflen -= 1;
-		break;
-
-	default:
-		if (*buflen < optlen + 2)
-			return -ENOBUFS;
-
-		if (!optval)
-			return -EINVAL;
-
-		(*buf)[0] = code;
-		(*buf)[1] = optlen;
-		memcpy(&(*buf)[2], optval, optlen);
-
-		*buf += optlen + 2;
-		*buflen -= (optlen + 2);
-
-		break;
-	}
-
-	return 0;
-}
-
 static void dhcp_message_set_address_type(struct dhcp_message *message,
 						uint8_t addr_type,
 						uint8_t addr_len)
-- 
2.26.2

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

* [PATCH 05/20] dhcp-transport: modify BPF filter for server
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (2 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 04/20] dhcp-util: move iter APIs to dhcp-util James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 16:31   ` Denis Kenzior
  2020-10-16 15:36 ` [PATCH 06/20] dhcp-transport: rename 'broadcast' op to 'l2_send' James Prestwood
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

In preparation for dhcp server the XID portion of the BPF
needs to be skipped when the port is DHCP_PORT_SERVER since
this value will not be present in messages going to the
server. The check for the message op was also changed to
include both BOOTREQUEST and BOOTREPLY depending if the
port matches the server or client port.
---
 ell/dhcp-transport.c | 8 +++++++-
 ell/dhcp.c           | 3 +--
 2 files changed, 8 insertions(+), 3 deletions(-)

v2:
 * Maintained the check for BOOTREPLY while also filtering for
   BOOTREQUEST in the server case
 * Maintained the check for XID in the client case but skip
   over this check for server.

diff --git a/ell/dhcp-transport.c b/ell/dhcp-transport.c
index e332f99..b693530 100644
--- a/ell/dhcp-transport.c
+++ b/ell/dhcp-transport.c
@@ -384,7 +384,9 @@ static int kernel_raw_socket_open(uint32_t ifindex, uint16_t port, uint32_t xid)
 				offsetof(struct dhcp_packet, dhcp.op)),
 		/* op == BOOTREPLY ? */
 		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K,
-				DHCP_OP_CODE_BOOTREPLY, 1, 0),
+				(port == DHCP_PORT_CLIENT) ?
+				DHCP_OP_CODE_BOOTREPLY :
+				DHCP_OP_CODE_BOOTREQUEST, 1, 0),
 		/* ignore */
 		BPF_STMT(BPF_RET + BPF_K, 0),
 		/* A <- DHCP header type */
@@ -394,6 +396,10 @@ static int kernel_raw_socket_open(uint32_t ifindex, uint16_t port, uint32_t xid)
 		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPHRD_ETHER, 1, 0),
 		/* ignore */
 		BPF_STMT(BPF_RET + BPF_K, 0),
+		/* A <- UDP destination port */
+		BPF_STMT(BPF_LD + BPF_H + BPF_ABS,
+				offsetof(struct dhcp_packet, udp.dest)),
+		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_PORT_SERVER, 3, 0),
 		/* A <- client identifier */
 		BPF_STMT(BPF_LD + BPF_W + BPF_ABS,
 				offsetof(struct dhcp_packet, dhcp.xid)),
diff --git a/ell/dhcp.c b/ell/dhcp.c
index e604dc0..12ed505 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -974,8 +974,7 @@ LIB_EXPORT bool l_dhcp_client_start(struct l_dhcp_client *client)
 		l_getrandom(&client->xid, sizeof(client->xid));
 
 	if (client->transport->open)
-		if (client->transport->open(client->transport,
-							client->xid) < 0)
+		if (client->transport->open(client->transport, client->xid) < 0)
 			return false;
 
 	_dhcp_transport_set_rx_callback(client->transport,
-- 
2.26.2

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

* [PATCH 06/20] dhcp-transport: rename 'broadcast' op to 'l2_send'
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (3 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 05/20] dhcp-transport: modify BPF filter for server James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 07/20] unit: update test-dhcp to use l2_send James Prestwood
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

The naming here was somewhat misleading. Functionally this was
being used as a broadcast only because the destination address
was a broadcast address. Really this operation was simply sending
out a packet on l2, which DHCP server requires except that it
needs to send to a specific MAC address, not broadcast to all.

The name was changed to better describe the API and a destination
mac argument was added to allow the server to use it. 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(-)

diff --git a/ell/dhcp-private.h b/ell/dhcp-private.h
index 3aa89fb..a1e1155 100644
--- a/ell/dhcp-private.h
+++ b/ell/dhcp-private.h
@@ -92,9 +92,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 b693530..8d890c6 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 12ed505..71a9ad9 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -368,9 +368,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);
 }
 
@@ -467,10 +468,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

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

* [PATCH 07/20] unit: update test-dhcp to use l2_send
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (4 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 06/20] dhcp-transport: rename 'broadcast' op to 'l2_send' James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 08/20] dhcp-lease: add mac member and getter James Prestwood
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

---
 unit/test-dhcp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/unit/test-dhcp.c b/unit/test-dhcp.c
index d825401..6ae8d71 100644
--- a/unit/test-dhcp.c
+++ b/unit/test-dhcp.c
@@ -673,9 +673,10 @@ static int fake_transport_send(struct dhcp_transport *transport,
 	return len;
 }
 
-static int fake_transport_broadcast(struct dhcp_transport *transprot,
+static int fake_transport_l2_send(struct dhcp_transport *transprot,
 					uint32_t saddr, uint16_t sport,
 					uint32_t daddr, uint16_t dport,
+					const uint8_t *dest_mac,
 					const void *data, size_t len)
 {
 	assert(len <= sizeof(client_packet));
@@ -702,7 +703,7 @@ static void test_discover(const void *data)
 	const struct l_dhcp_lease *lease;
 
 	transport->send = fake_transport_send;
-	transport->broadcast = fake_transport_broadcast;
+	transport->l2_send = fake_transport_l2_send;
 	transport->ifindex = 42;
 
 	client = l_dhcp_client_new(42);
-- 
2.26.2

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

* [PATCH 08/20] dhcp-lease: add mac member and getter
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (5 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 07/20] unit: update test-dhcp to use l2_send James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 09/20] dhcp: prepare for DHCP server James Prestwood
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

Added for server since it needs to track each clients
MAC address.
---
 ell/dhcp-lease.c   | 8 ++++++++
 ell/dhcp-private.h | 2 ++
 ell/dhcp.h         | 1 +
 3 files changed, 11 insertions(+)

diff --git a/ell/dhcp-lease.c b/ell/dhcp-lease.c
index ac90c6a..59de3e3 100644
--- a/ell/dhcp-lease.c
+++ b/ell/dhcp-lease.c
@@ -278,3 +278,11 @@ LIB_EXPORT uint32_t l_dhcp_lease_get_lifetime(const struct l_dhcp_lease *lease)
 
 	return lease->lifetime;
 }
+
+LIB_EXPORT const uint8_t *l_dhcp_lease_get_mac(const struct l_dhcp_lease *lease)
+{
+	if (unlikely(!lease))
+		return NULL;
+
+	return lease->mac;
+}
diff --git a/ell/dhcp-private.h b/ell/dhcp-private.h
index a1e1155..ddc0662 100644
--- a/ell/dhcp-private.h
+++ b/ell/dhcp-private.h
@@ -138,6 +138,8 @@ struct l_dhcp_lease {
 	uint32_t router;
 	uint32_t *dns;
 	char *domain_name;
+	/* for server */
+	uint8_t mac[6];
 };
 
 struct l_dhcp_lease *_dhcp_lease_new(void);
diff --git a/ell/dhcp.h b/ell/dhcp.h
index b8a5b41..c78b605 100644
--- a/ell/dhcp.h
+++ b/ell/dhcp.h
@@ -96,6 +96,7 @@ char *l_dhcp_lease_get_broadcast(const struct l_dhcp_lease *lease);
 char *l_dhcp_lease_get_server_id(const struct l_dhcp_lease *lease);
 char **l_dhcp_lease_get_dns(const struct l_dhcp_lease *lease);
 char *l_dhcp_lease_get_domain_name(const struct l_dhcp_lease *lease);
+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);
-- 
2.26.2

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

* [PATCH 09/20] dhcp: prepare for DHCP server
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (6 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 08/20] dhcp-lease: add mac member and getter James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 10/20] dhcp-server: basic DHCP server skeleton James Prestwood
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

Some defines were moved out of dhcp.c and into dhcp-private.h
so server can utilize them.
---
 ell/dhcp-private.h | 14 ++++++++++++++
 ell/dhcp.c         | 14 --------------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/ell/dhcp-private.h b/ell/dhcp-private.h
index ddc0662..8cd57fd 100644
--- a/ell/dhcp-private.h
+++ b/ell/dhcp-private.h
@@ -44,6 +44,8 @@ enum dhcp_op_code {
 	DHCP_OP_CODE_BOOTREPLY = 2,
 };
 
+#define DHCP_MIN_OPTIONS_SIZE 312
+
 #define DHCP_MAGIC 0x63825363
 
 /* RFC 2132, Section 9.6. DHCP Message Type */
@@ -51,6 +53,18 @@ enum dhcp_op_code {
 #define DHCP_OPTION_PAD 0 /* RFC 2132, Section 3.1 */
 #define DHCP_OPTION_END 255 /* RFC 2132, Section 3.2 */
 
+/* RFC 2132, Section 9.3. Option Overload */
+#define DHCP_OPTION_OVERLOAD 52
+enum dhcp_option_overload {
+	DHCP_OVERLOAD_FILE = 1,
+	DHCP_OVERLOAD_SNAME = 2,
+	DHCP_OVERLOAD_BOTH = 3,
+};
+
+#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* Section 9.8 */
+#define DHCP_OPTION_MAXIMUM_MESSAGE_SIZE 57 /* Section 9.10 */
+#define DHCP_OPTION_CLIENT_IDENTIFIER 61 /* Section 9.14 */
+
 /* RFC 2131, Figure 1 */
 struct dhcp_message {
 	uint8_t op;
diff --git a/ell/dhcp.c b/ell/dhcp.c
index 71a9ad9..8163068 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -50,18 +50,6 @@
 
 #define BITS_PER_LONG (sizeof(unsigned long) * 8)
 
-/* RFC 2132, Section 9.3. Option Overload */
-#define DHCP_OPTION_OVERLOAD 52
-enum dhcp_option_overload {
-	DHCP_OVERLOAD_FILE = 1,
-	DHCP_OVERLOAD_SNAME = 2,
-	DHCP_OVERLOAD_BOTH = 3,
-};
-
-#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* Section 9.8 */
-#define DHCP_OPTION_MAXIMUM_MESSAGE_SIZE 57 /* Section 9.10 */
-#define DHCP_OPTION_CLIENT_IDENTIFIER 61 /* Section 9.14 */
-
 enum dhcp_state {
 	DHCP_STATE_INIT,
 	DHCP_STATE_SELECTING,
@@ -175,8 +163,6 @@ static inline int dhcp_message_optimize(struct dhcp_message *message,
 	return len;
 }
 
-#define DHCP_MIN_OPTIONS_SIZE 312
-
 struct l_dhcp_client {
 	enum dhcp_state state;
 	unsigned long request_options[256 / BITS_PER_LONG];
-- 
2.26.2

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

* [PATCH 10/20] dhcp-server: basic DHCP server skeleton
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (7 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 09/20] dhcp: prepare for DHCP server James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 11/20] dhcp-server: add transport framework James Prestwood
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

---
 Makefile.am       |   1 +
 ell/dhcp-server.c | 343 ++++++++++++++++++++++++++++++++++++++++++++++
 ell/dhcp.h        |  39 ++++++
 3 files changed, 383 insertions(+)
 create mode 100644 ell/dhcp-server.c

v2:
 * Broke up the initial server implementation into several
   following commits.

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..f558493
--- /dev/null
+++ b/ell/dhcp-server.c
@@ -0,0 +1,343 @@
+/*
+ *
+ *  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)
+
+/* 5 minutes  */
+#define OFFER_TIME (5*60)
+
+#define SERVER_PORT 67
+
+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)
+
+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);
+}
+
+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)
+{
+	if (unlikely(!server))
+		return false;
+
+	if (server->started)
+		return false;
+
+	if (!server->address) {
+		struct in_addr ia;
+
+		if (!l_net_get_address(server->ifindex, &ia))
+			return false;
+
+		server->address = ia.s_addr;
+	}
+
+	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;
+
+	if (unlikely(!server || !start_ip || !end_ip))
+		return false;
+
+	if (inet_aton((const char *)start_ip, &_host_addr) == 0)
+		return false;
+
+	server->start_ip = _host_addr.s_addr;
+
+	if (inet_aton((const char *) end_ip, &_host_addr) == 0)
+		return false;
+
+	server->end_ip = _host_addr.s_addr;
+
+	return true;
+}
+
+LIB_EXPORT void 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;
+
+	server->debug_handler = function;
+	server->debug_data = user_data;
+}
+
+LIB_EXPORT void l_dhcp_server_set_lease_time(struct l_dhcp_server *server,
+					unsigned int lease_time)
+{
+	if (unlikely(!server))
+		return;
+
+	server->lease_seconds = lease_time;
+}
+
+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;
+}
+
+LIB_EXPORT const struct l_dhcp_lease *l_dhcp_server_get_lease(
+						struct l_dhcp_server *server,
+						const uint8_t *mac)
+{
+	if (unlikely(!server || !mac))
+		return NULL;
+
+	return find_lease_by_mac(server, mac);
+}
diff --git a/ell/dhcp.h b/ell/dhcp.h
index c78b605..2d630fe 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,33 @@ 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);
+void 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);
+void 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);
+const struct l_dhcp_lease *l_dhcp_server_get_lease(
+						struct l_dhcp_server *server,
+						const uint8_t *mac);
 #ifdef __cplusplus
 }
 #endif
-- 
2.26.2

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

* [PATCH 11/20] dhcp-server: add transport framework
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (8 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 10/20] dhcp-server: basic DHCP server skeleton James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 12/20] dhcp-server: process DISCOVER and send OFFER James Prestwood
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

---
 ell/dhcp-private.h |  4 ++++
 ell/dhcp-server.c  | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/ell/dhcp-private.h b/ell/dhcp-private.h
index 8cd57fd..a1fbcab 100644
--- a/ell/dhcp-private.h
+++ b/ell/dhcp-private.h
@@ -21,6 +21,7 @@
  */
 
 struct l_dhcp_client;
+struct l_dhcp_server;
 
 enum {
 	DHCP_PORT_SERVER = 67,
@@ -141,6 +142,9 @@ bool _dhcp_client_set_transport(struct l_dhcp_client *client,
 					struct dhcp_transport *transport);
 void _dhcp_client_override_xid(struct l_dhcp_client *client, uint32_t xid);
 
+bool _dhcp_server_set_transport(struct l_dhcp_server *server,
+					struct dhcp_transport *transport);
+
 struct l_dhcp_lease {
 	uint32_t address;
 	uint32_t server_address;
diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index f558493..c57b9ab 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -66,6 +66,8 @@ struct l_dhcp_server {
 	l_dhcp_server_event_cb_t event_handler;
 	void *user_data;
 	l_dhcp_destroy_cb_t event_destroy;
+
+	struct dhcp_transport *transport;
 };
 
 #define MAC "%02x:%02x:%02x:%02x:%02x:%02x"
@@ -98,6 +100,23 @@ 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 listener_event(const void *data, size_t len, void *user_data)
+{
+}
+
+bool _dhcp_server_set_transport(struct l_dhcp_server *server,
+					struct dhcp_transport *transport)
+{
+	if (unlikely(!server))
+		return false;
+
+	if (server->transport)
+		_dhcp_transport_free(server->transport);
+
+	server->transport = transport;
+	return true;
+}
+
 LIB_EXPORT struct l_dhcp_server *l_dhcp_server_new(int ifindex)
 {
 	struct l_dhcp_server *server = l_new(struct l_dhcp_server, 1);
@@ -127,6 +146,7 @@ LIB_EXPORT void l_dhcp_server_destroy(struct l_dhcp_server *server)
 	if (server->event_destroy)
 		server->event_destroy(server->user_data);
 
+	_dhcp_transport_free(server->transport);
 	l_free(server->ifname);
 
 	l_queue_destroy(server->lease_list,
@@ -162,8 +182,22 @@ LIB_EXPORT bool l_dhcp_server_start(struct l_dhcp_server *server)
 			return false;
 	}
 
+	if (!server->transport) {
+		server->transport = _dhcp_default_transport_new(server->ifindex,
+					server->ifname, DHCP_PORT_SERVER);
+		if (!server->transport)
+			return false;
+	}
+
 	SERVER_DEBUG("Starting DHCP server on %s", server->ifname);
 
+	if (server->transport->open)
+		if (server->transport->open(server->transport, 0) < 0)
+			return false;
+
+	_dhcp_transport_set_rx_callback(server->transport, listener_event,
+						server);
+
 	server->started = true;
 
 	return true;
@@ -177,6 +211,9 @@ LIB_EXPORT bool l_dhcp_server_stop(struct l_dhcp_server *server)
 	if (!server->started)
 		return true;
 
+	if (server->transport->close)
+		server->transport->close(server->transport);
+
 	server->started = false;
 
 	/* TODO: Add ability to save leases */
-- 
2.26.2

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

* [PATCH 12/20] dhcp-server: process DISCOVER and send OFFER
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (9 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 11/20] dhcp-server: add transport framework James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 13/20] dhcp-server: add REQUEST processing James Prestwood
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

Add handling of DISCOVER messages and ability to send offers.
---
 ell/dhcp-server.c | 321 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 321 insertions(+)

diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index c57b9ab..22a02eb 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -46,6 +46,14 @@
 
 #define SERVER_PORT 67
 
+static const uint8_t MAC_BCAST_ADDR[ETH_ALEN] __attribute__((aligned(2))) = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+static const uint8_t MAC_ANY_ADDR[ETH_ALEN] __attribute__((aligned(2))) = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
 struct l_dhcp_server {
 	bool started;
 	int ifindex;
@@ -86,6 +94,14 @@ 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 < time(NULL))
+		return true;
+
+	return false;
+}
+
 static bool match_lease_mac(const void *data, const void *user_data)
 {
 	const struct l_dhcp_lease *lease = data;
@@ -100,8 +116,313 @@ 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);
 }
 
+/* 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 (yiaddr < server->start_ip)
+		return -ENXIO;
+
+	if (yiaddr > server->end_ip)
+		return -ENXIO;
+
+	if (memcmp(mac, MAC_BCAST_ADDR, ETH_ALEN) == 0)
+		return -ENXIO;
+
+	if (memcmp(mac, MAC_ANY_ADDR, ETH_ALEN) == 0)
+		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);
+	if (!*lease_out)
+		return -ENOMEM;
+
+	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 = time(NULL) + 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_nip(struct l_dhcp_server *server,
+						uint32_t nip)
+{
+	return l_queue_find(server->lease_list, match_lease_ip,
+				L_INT_TO_PTR(nip));
+}
+
+static bool check_requested_nip(struct l_dhcp_server *server,
+				uint32_t requested_nip)
+{
+	struct l_dhcp_lease *lease;
+
+	if (requested_nip == 0)
+		return false;
+
+	if (requested_nip < server->start_ip)
+		return false;
+
+	if (requested_nip > server->end_ip)
+		return false;
+
+	lease = find_lease_by_nip(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 nip, const uint8_t *safe_mac)
+{
+	/* TODO: Add ARP checking */
+	return true;
+}
+
+static uint32_t find_free_or_expired_nip(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++) {
+		/* 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_nip(server, ip_addr);
+		if (lease)
+			continue;
+
+		if (arp_check(ip_addr, safe_mac))
+			return ip_addr;
+	}
+
+	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_nip)
+{
+	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_nip(server, requested_nip))
+		reply->yiaddr = requested_nip;
+	else
+		reply->yiaddr = find_free_or_expired_nip(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_UNALIGNED(
+							(const uint32_t *) v);
+
+			if (server->address != server_id_opt)
+				return;
+
+			break;
+		case L_DHCP_OPTION_REQUESTED_IP_ADDRESS:
+			if (l == 4)
+				requested_ip_opt = L_GET_UNALIGNED(
+							(const uint32_t *) 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] 22+ messages in thread

* [PATCH 13/20] dhcp-server: add REQUEST processing
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (10 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 12/20] dhcp-server: process DISCOVER and send OFFER James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 14/20] dhcp-server: handle DECLINE messages James Prestwood
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

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

diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index 22a02eb..4eb9aec 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -364,6 +364,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;
@@ -421,6 +488,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] 22+ messages in thread

* [PATCH 14/20] dhcp-server: handle DECLINE messages
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (11 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 13/20] dhcp-server: add REQUEST processing James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 15/20] dhcp-server: add RELEASE message support James Prestwood
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

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

diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index 4eb9aec..d2a1661 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -116,6 +116,18 @@ 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);
+
+	if (server->event_handler)
+		server->event_handler(server, L_DHCP_SERVER_EVENT_LEASE_EXPIRED,
+					server->user_data, 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,
@@ -509,6 +521,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] 22+ messages in thread

* [PATCH 15/20] dhcp-server: add RELEASE message support
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (12 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 14/20] dhcp-server: handle DECLINE messages James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 16/20] dhcp-server: add INFORM message handling James Prestwood
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 1534 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 | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/ell/dhcp-server.c b/ell/dhcp-server.c
index d2a1661..c74cd0b 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -205,6 +205,20 @@ static struct l_dhcp_lease *add_lease(struct l_dhcp_server *server,
 	return lease;
 }
 
+static void lease_set_expire(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;
@@ -530,6 +544,16 @@ 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_set_expire(server, lease, time(NULL));
+
 		break;
 	}
 }
-- 
2.26.2

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

* [PATCH 16/20] dhcp-server: add INFORM message handling
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (13 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 15/20] dhcp-server: add RELEASE message support James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 17/20] unit: update dhcp test to use new builder APIs James Prestwood
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 1636 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 c74cd0b..16f78f1 100644
--- a/ell/dhcp-server.c
+++ b/ell/dhcp-server.c
@@ -390,6 +390,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)
 {
@@ -555,6 +579,11 @@ static void listener_event(const void *data, size_t len, void *user_data)
 			lease_set_expire(server, lease, time(NULL));
 
 		break;
+	case DHCP_MESSAGE_TYPE_INFORM:
+		SERVER_DEBUG("Received INFORM");
+
+		send_inform(server, message);
+		break;
 	}
 }
 
-- 
2.26.2

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

* [PATCH 17/20] unit: update dhcp test to use new builder APIs
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (14 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 16/20] dhcp-server: add INFORM message handling James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 18/20] examples: basic DHCP server example James Prestwood
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

---
 unit/test-dhcp.c | 83 +++++++++++++++++++++---------------------------
 1 file changed, 37 insertions(+), 46 deletions(-)

diff --git a/unit/test-dhcp.c b/unit/test-dhcp.c
index 6ae8d71..955ed29 100644
--- a/unit/test-dhcp.c
+++ b/unit/test-dhcp.c
@@ -33,7 +33,7 @@
 #include <ell/ell.h>
 #include "ell/dhcp-private.h"
 
-static bool verbose = false;
+static bool verbose = true;
 static uint8_t client_packet[1024];
 static size_t client_packet_len;
 
@@ -365,9 +365,13 @@ static void test_option_8(const void *data)
 
 static void test_option_set(const void *data)
 {
-	static uint8_t result[64] = {'A', 'B', 'C', 'D' };
+	struct dhcp_message_builder builder;
+	struct dhcp_message *message;
+	size_t outlen;
+	uint8_t *msg_out;
+	unsigned int i;
+	static uint8_t result[sizeof(struct dhcp_message) + 64];
 	static uint8_t options[64] = {
-			'A', 'B', 'C', 'D',
 			160, 2, 0x11, 0x12,
 			0,
 			31, 8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
@@ -377,51 +381,38 @@ static void test_option_set(const void *data)
 			255
 	};
 
-	size_t len, oldlen;
-	int pos, i;
-	uint8_t *opt;
+	message = (struct dhcp_message *)result;
 
-	assert(_dhcp_option_append(NULL, NULL, 0, 0, NULL) == -EINVAL);
-
-	len = 0;
-	opt = &result[0];
-	assert(_dhcp_option_append(&opt, NULL, 0, 0, NULL) == -EINVAL);
-	assert(opt == &result[0] && len == 0);
-
-	assert(_dhcp_option_append(&opt, &len, 0, 0, NULL) == -ENOBUFS);
-	assert(opt == &result[0] && len == 0);
-
-	opt = &result[4];
-	len = 1;
-	assert(_dhcp_option_append(&opt, &len, 0, 0, NULL) >= 0);
-	assert(opt == &result[5] && len == 0);
-
-	pos = 4;
-	len = 60;
-	while (pos < 64 && options[pos] != 255) {
-		opt = &result[pos];
-		oldlen = len;
-
-		assert(_dhcp_option_append(&opt, &len, options[pos],
-						options[pos + 1],
-						&options[pos + 2]) >= 0);
-
-		if (options[pos] == 0) {
-			assert(opt == &result[pos + 1]);
-			assert(len == oldlen - 1);
-			pos++;
-		} else {
-			assert(opt == &result[pos + 2 + options[pos + 1]]);
-			assert(len == oldlen - 2 - options[pos + 1]);
-			pos += 2 + options[pos + 1];
-		}
-	}
+	/* test a few failure conditions */
+	assert(!_dhcp_message_builder_init(NULL, NULL, 0, 0));
+	assert(!_dhcp_message_builder_init(&builder, message, 0, 0));
+
+	_dhcp_message_builder_init(&builder, message, sizeof(result),
+					DHCP_MESSAGE_TYPE_DISCOVER);
+	_dhcp_message_builder_append(&builder, 160, 2, options + 2);
+	_dhcp_message_builder_append(&builder, 0, 0, NULL);
+	_dhcp_message_builder_append(&builder, 31, 8, options + 7);
+	_dhcp_message_builder_append(&builder, 0, 0, NULL);
+	_dhcp_message_builder_append(&builder, 55, 3, options + 18);
+	_dhcp_message_builder_append(&builder, 17, 7, options + 23);
+	msg_out = _dhcp_message_builder_finalize(&builder, &outlen);
 
-	for (i = 0; i < pos; i++) {
-		if (verbose)
-			l_info("%2d: 0x%02x(0x%02x)\n",
-					i, result[i], options[i]);
-		assert(result[i] == options[i]);
+	/*
+	 * The builde APIs automatically append the type passed in during init
+	 * so we can skip over that in order to test the expected static data
+	 */
+
+	msg_out += sizeof(struct dhcp_message) + 3;
+
+	for (i = 0; i < outlen - sizeof(struct dhcp_message); i++) {
+		if (msg_out[i] != options[i]) {
+			if (verbose) {
+				l_info("byte[%d] did not match 0x%02x 0x%02x",
+					i, msg_out[i], options[i]);
+			}
+
+			assert(false);
+		}
 	}
 }
 
-- 
2.26.2

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

* [PATCH 18/20] examples: basic DHCP server example
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (15 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 17/20] unit: update dhcp test to use new builder APIs James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 19/20] unit: add complete client/server dhcp test James Prestwood
  2020-10-16 15:36 ` [PATCH 20/20] dhcp: Add support for setting address James Prestwood
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

---
 .gitignore             |   1 +
 Makefile.am            |   4 +-
 examples/dhcp-server.c | 129 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 133 insertions(+), 1 deletion(-)
 create mode 100644 examples/dhcp-server.c

diff --git a/.gitignore b/.gitignore
index c3d2790..e963359 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,6 +76,7 @@ examples/dbus-client
 examples/glib-eventloop
 examples/dhcp-client
 examples/dhcp6-client
+examples/dhcp-server
 test-suite.log
 tools/certchain-verify
 tools/genl-discover
diff --git a/Makefile.am b/Makefile.am
index 9bdf4dc..adedd1f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -326,7 +326,8 @@ unit_test_data_files = unit/settings.test unit/dbus.conf
 
 examples = examples/dbus-service examples/https-client-test \
 		examples/https-server-test examples/dbus-client \
-		examples/dhcp-client examples/dhcp6-client
+		examples/dhcp-client examples/dhcp6-client \
+		examples/dhcp-server
 
 if GLIB
 examples += examples/glib-eventloop
@@ -344,6 +345,7 @@ examples_glib_eventloop_CFLAGS = @GLIB_CFLAGS@
 examples_glib_eventloop_LDADD = ell/libell-private.la @GLIB_LIBS@
 examples_dhcp_client_LDADD = ell/libell-private.la
 examples_dhcp6_client_LDADD = ell/libell-private.la
+examples_dhcp_server_LDADD = ell/libell-private.la
 
 noinst_PROGRAMS += tools/certchain-verify tools/genl-discover \
 		   tools/genl-watch tools/genl-request tools/gpio
diff --git a/examples/dhcp-server.c b/examples/dhcp-server.c
new file mode 100644
index 0000000..33c0983
--- /dev/null
+++ b/examples/dhcp-server.c
@@ -0,0 +1,129 @@
+/*
+ *
+ *  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
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <linux/if_arp.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ell/ell.h>
+
+static void do_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	l_info("%s%s", prefix, str);
+}
+
+static void signal_handler(uint32_t signo, void *user_data)
+{
+	switch (signo) {
+	case SIGINT:
+	case SIGTERM:
+		l_info("Terminate");
+		l_main_quit();
+		break;
+	}
+}
+
+static void destroy_handler(void *data)
+{
+	l_info("DHCP server destroyed");
+}
+
+static void event_handler(struct l_dhcp_server *server,
+					enum l_dhcp_server_event event,
+					void *userdata,
+					const struct l_dhcp_lease *lease)
+{
+	const uint8_t *mac;
+	char *ip;
+
+	switch (event) {
+	case L_DHCP_SERVER_EVENT_NEW_LEASE:
+		mac = l_dhcp_lease_get_mac(lease);
+		ip = l_dhcp_lease_get_address(lease);
+
+		l_info("New lease client %02x:%02x:%02x:%02x:%02x:%02x %s",
+				mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+				ip);
+		l_free(ip);
+		break;
+	case L_DHCP_SERVER_EVENT_LEASE_EXPIRED:
+		break;
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	struct l_dhcp_server *server;
+	int ifindex;
+	uint8_t mac[6];
+	char *dns[] = { "192.168.1.1", NULL };
+
+	if (argc < 2) {
+		printf("Usage: %s <interface index>\n", argv[0]);
+		exit(0);
+	}
+
+	ifindex = atoi(argv[1]);
+
+	if (!l_net_get_mac_address(ifindex, mac)) {
+		printf("Unable to get address from interface %d\n", ifindex);
+		exit(0);
+	}
+
+	if (!l_main_init())
+		return -1;
+
+	l_log_set_stderr();
+	l_debug_enable("*");
+
+	server = l_dhcp_server_new(ifindex);
+	l_dhcp_server_set_ip_range(server, "192.168.1.2", "192.168.1.100");
+	l_dhcp_server_set_netmask(server, "255.255.255.0");
+	l_dhcp_server_set_gateway(server, "192.168.1.1");
+	l_dhcp_server_set_dns(server, dns);
+	l_dhcp_server_set_lease_time(server, 10);
+	l_dhcp_server_set_debug(server, do_debug, "[DHCP SERV] ", NULL);
+	l_dhcp_server_set_event_handler(server, event_handler, NULL,
+						destroy_handler);
+	l_dhcp_server_start(server);
+
+	l_main_run_with_signal(signal_handler, NULL);
+
+	l_dhcp_server_stop(server);
+	l_dhcp_server_destroy(server);
+	l_main_exit();
+
+	return 0;
+}
-- 
2.26.2

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

* [PATCH 19/20] unit: add complete client/server dhcp test
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (16 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 18/20] examples: basic DHCP server example James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  2020-10-16 15:36 ` [PATCH 20/20] dhcp: Add support for setting address James Prestwood
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

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

diff --git a/unit/test-dhcp.c b/unit/test-dhcp.c
index 955ed29..beb9109 100644
--- a/unit/test-dhcp.c
+++ b/unit/test-dhcp.c
@@ -36,6 +36,8 @@
 static bool verbose = true;
 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,173 @@ 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 server_event_handler(struct l_dhcp_server *server,
+					enum l_dhcp_server_event event,
+					void *userdata,
+					const struct l_dhcp_lease *lease)
+{
+	const uint8_t expected_mac[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+	const uint8_t *mac;
+	char *ip;
+
+	switch (event) {
+	case L_DHCP_SERVER_EVENT_NEW_LEASE:
+		mac = l_dhcp_lease_get_mac(lease);
+		ip = l_dhcp_lease_get_address(lease);
+
+		assert(!memcmp(mac, expected_mac, sizeof(expected_mac)));
+		assert(!strcmp(ip, "192.168.1.2"));
+
+		l_free(ip);
+		break;
+	case L_DHCP_SERVER_EVENT_LEASE_EXPIRED:
+		break;
+	}
+}
+
+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 addr[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+	char *dns[] = { "192.168.1.1", "192.168.1.254", NULL };
+	struct l_dhcp_client *client;
+	struct l_dhcp_server *server;
+	struct dhcp_transport *cli_transport = l_new(struct dhcp_transport, 1);
+	struct dhcp_transport *srv_transport = l_new(struct dhcp_transport, 1);
+	const struct l_dhcp_lease *cli_lease;
+	const struct l_dhcp_lease *srv_lease;
+	/* client IP address */
+	char *cli_addr;
+	/* servers leased IP address, should match cli_addr */
+	char *srv_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));
+	assert(l_dhcp_server_set_event_handler(server, server_event_handler,
+						NULL, NULL));
+
+	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));
+
+	client = l_dhcp_client_new(42);
+
+	assert(l_dhcp_client_set_address(client, ARPHRD_ETHER, addr, 6));
+	assert(l_dhcp_client_set_interface_name(client, "fake"));
+	assert(l_dhcp_client_set_hostname(client, "<hostname>"));
+	_dhcp_client_override_xid(client, 0x4d7c67c6);
+	assert(l_dhcp_client_set_event_handler(client,
+				event_handler_lease_obtained, NULL, NULL));
+
+	if (verbose)
+		l_dhcp_client_set_debug(client, do_debug, "[DHCP] ", NULL);
+
+	cli_transport->send = fake_transport_send;
+	cli_transport->l2_send = fake_transport_l2_send;
+	cli_transport->ifindex = 42;
+
+	assert(_dhcp_client_set_transport(client, cli_transport));
+
+	assert(l_dhcp_client_start(client));
+
+	/* RX DISCOVER */
+	srv_transport->rx_cb(client_packet, client_packet_len, server);
+	assert(l2_send_called);
+	l2_send_called = false;
+
+	/* RX OFFER */
+	cli_transport->rx_cb(server_packet, server_packet_len, client);
+
+	/* RX REQUEST */
+	srv_transport->rx_cb(client_packet, client_packet_len, server);
+	assert(l2_send_called);
+	l2_send_called = false;
+
+	/* RX ACK */
+	cli_transport->rx_cb(server_packet, server_packet_len, client);
+
+	assert(event_handler_called);
+
+	cli_lease = l_dhcp_client_get_lease(client);
+	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);
+
+	srv_lease = l_dhcp_server_get_lease(server, addr);
+	assert(srv_lease);
+	srv_cli_addr = l_dhcp_lease_get_address(srv_lease);
+	assert(!strcmp(cli_addr, srv_cli_addr));
+
+	l_free(cli_addr);
+	l_free(srv_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);
+
+	l_dhcp_client_stop(client);
+	l_dhcp_client_destroy(client);
+
+	l_dhcp_server_stop(server);
+	l_dhcp_server_destroy(server);
+}
+
 int main(int argc, char *argv[])
 {
 	l_test_init(&argc, &argv);
@@ -759,5 +928,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] 22+ messages in thread

* [PATCH 20/20] dhcp: Add support for setting address
  2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
                   ` (17 preceding siblings ...)
  2020-10-16 15:36 ` [PATCH 19/20] unit: add complete client/server dhcp test James Prestwood
@ 2020-10-16 15:36 ` James Prestwood
  18 siblings, 0 replies; 22+ messages in thread
From: James Prestwood @ 2020-10-16 15:36 UTC (permalink / raw)
  To: ell

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

Add optional support for the dhcp client to set the DHCP
address automatically. This is done by providing an RTNL
object with l_dhcp_client_set_rtnl.
---
 ell/dhcp.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ell/dhcp.h |  4 ++++
 2 files changed, 74 insertions(+)

diff --git a/ell/dhcp.c b/ell/dhcp.c
index 8163068..63076f4 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -38,6 +38,8 @@
 #include "timeout.h"
 #include "dhcp.h"
 #include "dhcp-private.h"
+#include "netlink.h"
+#include "rtnl.h"
 
 #define CLIENT_DEBUG(fmt, args...)					\
 	l_util_debug(client->debug_handler, client->debug_data,		\
@@ -178,6 +180,9 @@ struct l_dhcp_client {
 	struct l_timeout *timeout_resend;
 	struct l_timeout *timeout_lease;
 	struct l_dhcp_lease *lease;
+	struct l_netlink *rtnl;
+	uint32_t rtnl_add_cmdid;
+	struct l_rtnl_address *rtnl_configured_address;
 	uint8_t attempt;
 	l_dhcp_client_event_cb_t event_handler;
 	void *event_data;
@@ -583,6 +588,24 @@ error:
 	l_dhcp_client_stop(client);
 }
 
+static void dhcp_client_address_add_cb(int error, uint16_t type,
+						const void *data, uint32_t len,
+						void *user_data)
+{
+	struct l_dhcp_client *client = user_data;
+
+	client->rtnl_add_cmdid = 0;
+
+	if (error < 0 && error != -EEXIST) {
+		l_rtnl_address_free(client->rtnl_configured_address);
+		client->rtnl_configured_address = NULL;
+		CLIENT_DEBUG("Unable to set address on ifindex: %u: %d(%s)",
+				client->ifindex, error,
+				strerror(-error));
+		return;
+	}
+}
+
 static int dhcp_client_receive_ack(struct l_dhcp_client *client,
 					const struct dhcp_message *ack,
 					size_t len)
@@ -626,6 +649,27 @@ static int dhcp_client_receive_ack(struct l_dhcp_client *client,
 			client->state == DHCP_STATE_REBOOTING)
 		r = L_DHCP_CLIENT_EVENT_LEASE_OBTAINED;
 
+	if (client->rtnl) {
+		struct l_rtnl_address *a;
+		L_AUTO_FREE_VAR(char *, ip) =
+			l_dhcp_lease_get_address(client->lease);
+		uint8_t prefix_len = 24;
+		uint32_t l = l_dhcp_lease_get_lifetime(client->lease);
+
+		a = l_rtnl_address_new(ip, prefix_len);
+		l_rtnl_address_set_noprefixroute(a, true);
+		l_rtnl_address_set_lifetimes(a, l, l);
+
+		client->rtnl_add_cmdid =
+			l_rtnl_ifaddr_add(client->rtnl, client->ifindex, a,
+						dhcp_client_address_add_cb,
+						client, NULL);
+		if (client->rtnl_add_cmdid)
+			client->rtnl_configured_address = a;
+		else
+			CLIENT_DEBUG("Configuring address via RTNL failed");
+	}
+
 	return r;
 }
 
@@ -988,6 +1032,19 @@ LIB_EXPORT bool l_dhcp_client_stop(struct l_dhcp_client *client)
 	if (unlikely(!client))
 		return false;
 
+	if (client->rtnl_add_cmdid) {
+		l_netlink_cancel(client->rtnl, client->rtnl_add_cmdid);
+		client->rtnl_add_cmdid = 0;
+	}
+
+	if (client->rtnl_configured_address) {
+		l_rtnl_ifaddr_delete(client->rtnl, client->ifindex,
+					client->rtnl_configured_address,
+					NULL, NULL, NULL);
+		l_rtnl_address_free(client->rtnl_configured_address);
+		client->rtnl_configured_address = NULL;
+	}
+
 	l_timeout_remove(client->timeout_resend);
 	client->timeout_resend = NULL;
 
@@ -1041,3 +1098,16 @@ LIB_EXPORT bool l_dhcp_client_set_debug(struct l_dhcp_client *client,
 
 	return true;
 }
+
+LIB_EXPORT bool l_dhcp_client_set_rtnl(struct l_dhcp_client *client,
+					struct l_netlink *rtnl)
+{
+	if (unlikely(!client))
+		return false;
+
+	if (unlikely(client->state != DHCP_STATE_INIT))
+		return false;
+
+	client->rtnl = rtnl;
+	return true;
+}
diff --git a/ell/dhcp.h b/ell/dhcp.h
index 2d630fe..a4c185c 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_netlink;
 struct l_dhcp_server;
 
 /* RFC 2132 */
@@ -85,6 +86,9 @@ bool l_dhcp_client_set_interface_name(struct l_dhcp_client *client,
 bool l_dhcp_client_set_hostname(struct l_dhcp_client *client,
 							const char *hostname);
 
+bool l_dhcp_client_set_rtnl(struct l_dhcp_client *client,
+					struct l_netlink *rtnl);
+
 const struct l_dhcp_lease *l_dhcp_client_get_lease(
 					const struct l_dhcp_client *client);
 
-- 
2.26.2

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

* Re: [PATCH 04/20] dhcp-util: move iter APIs to dhcp-util
  2020-10-16 15:36 ` [PATCH 04/20] dhcp-util: move iter APIs to dhcp-util James Prestwood
@ 2020-10-16 16:24   ` Denis Kenzior
  0 siblings, 0 replies; 22+ messages in thread
From: Denis Kenzior @ 2020-10-16 16:24 UTC (permalink / raw)
  To: ell

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

On 10/16/20 10:36 AM, James Prestwood wrote:
> These were already exposed for use elsewhere but dhcp-util
> is a better home for these APIs.
> ---
>   ell/dhcp-util.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++
>   ell/dhcp.c      | 160 ------------------------------------------------
>   2 files changed, 160 insertions(+), 160 deletions(-)

I went ahead and applied patches 1, 9, 2, 3, 4 in that order.  Patch 2 depended 
on some defines which weren't moved until patch 9.

Regards,
-Denis

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

* Re: [PATCH 05/20] dhcp-transport: modify BPF filter for server
  2020-10-16 15:36 ` [PATCH 05/20] dhcp-transport: modify BPF filter for server James Prestwood
@ 2020-10-16 16:31   ` Denis Kenzior
  0 siblings, 0 replies; 22+ messages in thread
From: Denis Kenzior @ 2020-10-16 16:31 UTC (permalink / raw)
  To: ell

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

Hi James,

On 10/16/20 10:36 AM, James Prestwood wrote:
> In preparation for dhcp server the XID portion of the BPF
> needs to be skipped when the port is DHCP_PORT_SERVER since
> this value will not be present in messages going to the
> server. The check for the message op was also changed to
> include both BOOTREQUEST and BOOTREPLY depending if the
> port matches the server or client port.
> ---
>   ell/dhcp-transport.c | 8 +++++++-
>   ell/dhcp.c           | 3 +--
>   2 files changed, 8 insertions(+), 3 deletions(-)
> 
> v2:
>   * Maintained the check for BOOTREPLY while also filtering for
>     BOOTREQUEST in the server case
>   * Maintained the check for XID in the client case but skip
>     over this check for server.
> 
> diff --git a/ell/dhcp-transport.c b/ell/dhcp-transport.c
> index e332f99..b693530 100644
> --- a/ell/dhcp-transport.c
> +++ b/ell/dhcp-transport.c
> @@ -384,7 +384,9 @@ static int kernel_raw_socket_open(uint32_t ifindex, uint16_t port, uint32_t xid)
>   				offsetof(struct dhcp_packet, dhcp.op)),
>   		/* op == BOOTREPLY ? */

I updated the comment slightly here

>   		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K,
> -				DHCP_OP_CODE_BOOTREPLY, 1, 0),
> +				(port == DHCP_PORT_CLIENT) ?
> +				DHCP_OP_CODE_BOOTREPLY :
> +				DHCP_OP_CODE_BOOTREQUEST, 1, 0),
>   		/* ignore */
>   		BPF_STMT(BPF_RET + BPF_K, 0),
>   		/* A <- DHCP header type */
> @@ -394,6 +396,10 @@ static int kernel_raw_socket_open(uint32_t ifindex, uint16_t port, uint32_t xid)
>   		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPHRD_ETHER, 1, 0),
>   		/* ignore */
>   		BPF_STMT(BPF_RET + BPF_K, 0),
> +		/* A <- UDP destination port */
> +		BPF_STMT(BPF_LD + BPF_H + BPF_ABS,
> +				offsetof(struct dhcp_packet, udp.dest)),
> +		BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_PORT_SERVER, 3, 0),
>   		/* A <- client identifier */
>   		BPF_STMT(BPF_LD + BPF_W + BPF_ABS,
>   				offsetof(struct dhcp_packet, dhcp.xid)),
> diff --git a/ell/dhcp.c b/ell/dhcp.c
> index e604dc0..12ed505 100644
> --- a/ell/dhcp.c
> +++ b/ell/dhcp.c
> @@ -974,8 +974,7 @@ LIB_EXPORT bool l_dhcp_client_start(struct l_dhcp_client *client)
>   		l_getrandom(&client->xid, sizeof(client->xid));
>   
>   	if (client->transport->open)
> -		if (client->transport->open(client->transport,
> -							client->xid) < 0)
> +		if (client->transport->open(client->transport, client->xid) < 0)
>   			return false;
>   
>   	_dhcp_transport_set_rx_callback(client->transport,
> 

And I dropped this chunk since it was formatting only and not related to the change.

Applied, thanks.

Regards,
-Denis

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

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

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-16 15:36 [PATCH 01/20] net: add l_net_get_address() James Prestwood
2020-10-16 15:36 ` [PATCH 02/20] dhcp-util: add dhcp message builder APIs James Prestwood
2020-10-16 15:36 ` [PATCH 03/20] dhcp: update client code to use " James Prestwood
2020-10-16 15:36 ` [PATCH 04/20] dhcp-util: move iter APIs to dhcp-util James Prestwood
2020-10-16 16:24   ` Denis Kenzior
2020-10-16 15:36 ` [PATCH 05/20] dhcp-transport: modify BPF filter for server James Prestwood
2020-10-16 16:31   ` Denis Kenzior
2020-10-16 15:36 ` [PATCH 06/20] dhcp-transport: rename 'broadcast' op to 'l2_send' James Prestwood
2020-10-16 15:36 ` [PATCH 07/20] unit: update test-dhcp to use l2_send James Prestwood
2020-10-16 15:36 ` [PATCH 08/20] dhcp-lease: add mac member and getter James Prestwood
2020-10-16 15:36 ` [PATCH 09/20] dhcp: prepare for DHCP server James Prestwood
2020-10-16 15:36 ` [PATCH 10/20] dhcp-server: basic DHCP server skeleton James Prestwood
2020-10-16 15:36 ` [PATCH 11/20] dhcp-server: add transport framework James Prestwood
2020-10-16 15:36 ` [PATCH 12/20] dhcp-server: process DISCOVER and send OFFER James Prestwood
2020-10-16 15:36 ` [PATCH 13/20] dhcp-server: add REQUEST processing James Prestwood
2020-10-16 15:36 ` [PATCH 14/20] dhcp-server: handle DECLINE messages James Prestwood
2020-10-16 15:36 ` [PATCH 15/20] dhcp-server: add RELEASE message support James Prestwood
2020-10-16 15:36 ` [PATCH 16/20] dhcp-server: add INFORM message handling James Prestwood
2020-10-16 15:36 ` [PATCH 17/20] unit: update dhcp test to use new builder APIs James Prestwood
2020-10-16 15:36 ` [PATCH 18/20] examples: basic DHCP server example James Prestwood
2020-10-16 15:36 ` [PATCH 19/20] unit: add complete client/server dhcp test James Prestwood
2020-10-16 15:36 ` [PATCH 20/20] dhcp: Add support for setting address 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.