summaryrefslogtreecommitdiff
path: root/libdhcp
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-04 12:49:09 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-04 12:49:15 -0700
commitea73a6242446f33951e5daa342e827bef700b835 (patch)
tree041e0563189ef7502ba61e96aeb344ce927c946d /libdhcp
parent3c81186daf97cf7011fd2806dfd0bc3b875e92f3 (diff)
wip dhcplukeshu/dhcp
Diffstat (limited to 'libdhcp')
-rw-r--r--libdhcp/CMakeLists.txt2
-rw-r--r--libdhcp/client.c (renamed from libdhcp/dhcp.c)123
-rw-r--r--libdhcp/include/libdhcp/client.h (renamed from libdhcp/include/libdhcp/dhcp.h)42
3 files changed, 80 insertions, 87 deletions
diff --git a/libdhcp/CMakeLists.txt b/libdhcp/CMakeLists.txt
index a14fd50..3830217 100644
--- a/libdhcp/CMakeLists.txt
+++ b/libdhcp/CMakeLists.txt
@@ -6,7 +6,7 @@
add_library(libdhcp INTERFACE)
target_include_directories(libdhcp SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_sources(libdhcp INTERFACE
- dhcp.c
+ client.c
)
target_link_libraries(libdhcp INTERFACE
libmisc
diff --git a/libdhcp/dhcp.c b/libdhcp/client.c
index 9786018..b8f1001 100644
--- a/libdhcp/dhcp.c
+++ b/libdhcp/client.c
@@ -1,4 +1,4 @@
-/* libdhcp/dhcp.c - A DHCP client
+/* libdhcp/client.c - A DHCP client
*
* Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -68,7 +68,8 @@
#include <libmisc/endian.h>
#include <libmisc/vcall.h>
-#include <libdhcp/dhcp.h>
+
+#include <libdhcp/client.h>
/* Config *********************************************************************/
@@ -83,6 +84,9 @@
#ifndef CONFIG_DHCP_SECS
#define CONFIG_DHCP_SECS 0
#endif
+#ifndef CONFIG_DHCP_SELECTING_NS
+ #define CONFIG_DHCP_SELECTING_NS (5*NS_PER_S)
+#endif
#ifndef CONFIG_DHCP_OPT_SIZE
#define CONFIG_DHCP_OPT_SIZE 312
#endif
@@ -449,28 +453,38 @@ static void dhcp_send_DECLINE(implements_net_packet_conn *sock) {
VCALL(sock, sendto, pDHCPMSG, DHCP_MSG_BASE_SIZE + k, net_ip4_addr_broadcast, DHCP_PORT_SERVER);
}
-static int8_t dhcp_msg_parse(implements_net_packet_conn *sock) {
+/**
+ * @return
+ * - <0: -errno
+ * - 0: ???
+ * - >0 && <= UINT8_MAX: msgtyp
+ * - >UINT8_MAX: ???
+ */
+static int dhcp_recv_msg(implements_net_packet_conn *sock) {
struct net_ip4_addr srv_addr;
uint16_t srv_port;
- size_t msg_len;
+ ssize_t msg_len;
+ restart:
msg_len = VCALL(sock, recvfrom, pDHCPMSG, sizeof(*pDHCPMSG), &srv_addr, &srv_port);
+ if (msg_len < 0)
+ return msg_len;
debugf("DHCP message : %d.%d.%d.%d(%d) %d received.",
srv_addr.octets[0], srv_addr.octets[1], srv_addr.octets[2], srv_addr.octets[3], srv_port, msg_len);
/* Compare server port. */
if (srv_port != DHCP_PORT_SERVER) {
- return 0;
+ goto restart;
}
/* Compare our MAC address. */
if (memcmp(pDHCPMSG->chaddr, self_eth_addr.octets, sizeof(self_eth_addr))) {
debugf("Not my DHCP Message. This message is ignored.");
- return 0;
+ goto restart;
}
/* Compare server IP address. */
if (memcmp(DHCP_SIP.octets, ((struct net_ip4_addr){0}).octets, sizeof(struct net_ip4_addr))) {
if ( memcmp(srv_addr.octets, DHCP_SIP.octets, sizeof(srv_addr)) &&
memcmp(srv_addr.octets, DHCP_REAL_SIP.octets, sizeof(srv_addr)) ) {
debugf("Another DHCP sever send a response message. This is ignored.");
- return 0;
+ goto restart;
}
}
@@ -595,10 +609,10 @@ static int8_t dhcp_check_leasedIP(implements_net_packet_conn *sock) {
return 0;
}
-COROUTINE DHCP_cr(struct w5500 *chip, uint8_t socknum,
- struct net_eth_addr self_eth_addr,
- char *self_hostname,
- dhcp_callback_t cb) {
+COROUTINE dhcp_client_cr(struct w5500 *chip, uint8_t socknum,
+ struct net_eth_addr self_eth_addr,
+ char *self_hostname,
+ dhcp_callback_t cb) {
uint32_t xid;
implements_net_packet_conn *sock;
@@ -613,58 +627,65 @@ COROUTINE DHCP_cr(struct w5500 *chip, uint8_t socknum,
dhcp_tick_1s = 0;
dhcp_tick_next = DHCP_WAIT_TIME;
dhcp_retry_count = 0;
- dhcp_state = STATE_DHCP_INIT;
sock = w5500_udp_conn(chip, socknum, DHCP_PORT_CLIENT);
- ret = DHCP_RET_RUNNING;
- msg_type = dhcp_msg_parse(sock);
+ int r;
+
+ dhcp_state = STATE_DHCP_INIT;
+ uint64_t time_ns_init;
for (;;) {
/* State transition diagram: https://datatracker.ietf.org/doc/html/rfc2131#page-35 */
switch (state) {
- case STATE_DHCP_INIT:
- dhcp_send_DISCOVER(sock);
- dhcp_state = STATE_DHCP_DISCOVER;
- break;
- case STATE_DHCP_DISCOVER :
- if (msg_type == DHCP_MSGTYP_OFFER){
- debugf("> Receive DHCP_OFFER");
- global_lease.addr = pDHCPMSG->yiaddr;
-
- dhcp_send_REQUEST(sock);
- dhcp_state = STATE_DHCP_REQUEST;
- } else
- ret = dhcp_check_timeout(sock);
- break;
+ case STATE_DHCP_INIT:
+ dhcp_send_DISCOVER(sock);
+ time_ns_init = VCALL(bootclock, get_time_ns);
+ VCALL(sock, set_read_deadline(time_ns_init+CONFIG_DHCP_SELECTING_NS));
+ dhcp_state = STATE_DHCP_SELECTING;
+ break;
+ case STATE_DHCP_SELECTING :
+ switch ((r = dhcp_recv_msg(sock))) {
+ case DHCP_MSGTYP_OFFER:
+ debugf("> Receive DHCP_OFFER");
+ global_lease.addr = pDHCPMSG->yiaddr;
+ dhcp_send_REQUEST(sock);
+ dhcp_state = STATE_DHCP_REQUEST;
+ break;
+ case -NET_ETIMEDOUT:
+ break;
+ default:
+ debugf("unexpected error: %d", r);
+ }
+ break;
- case STATE_DHCP_REQUEST :
- if (msg_type == DHCP_MSGTYP_ACK) {
- debugf("> Receive DHCP_ACK");
- if (dhcp_check_leasedIP(sock)) {
- /* Network info assignment from DHCP */
- cb(DHCP_ASSIGN, global_lease);
- dhcp_reset_timeout();
+ case STATE_DHCP_REQUEST :
+ if (msg_type == DHCP_MSGTYP_ACK) {
+ debugf("> Receive DHCP_ACK");
+ if (dhcp_check_leasedIP(sock)) {
+ /* Network info assignment from DHCP */
+ cb(DHCP_ASSIGN, global_lease);
+ dhcp_reset_timeout();
+
+ dhcp_state = STATE_DHCP_LEASED;
+ } else {
+ /* IP address conflict occurred */
+ dhcp_reset_timeout();
+ cb(DHCP_CONFLICT, global_lease);
+ dhcp_state = STATE_DHCP_INIT;
+ }
+ } else if (msg_type == DHCP_MSGTYP_NAK) {
+ debugf("> Receive DHCP_NACK");
- dhcp_state = STATE_DHCP_LEASED;
- } else {
- /* IP address conflict occurred */
dhcp_reset_timeout();
- cb(DHCP_CONFLICT, global_lease);
- dhcp_state = STATE_DHCP_INIT;
- }
- } else if (msg_type == DHCP_MSGTYP_NAK) {
- debugf("> Receive DHCP_NACK");
- dhcp_reset_timeout();
-
- dhcp_state = STATE_DHCP_DISCOVER;
- } else
- ret = dhcp_check_timeout(sock);
- break;
+ dhcp_state = STATE_DHCP_DISCOVER;
+ } else
+ ret = dhcp_check_timeout(sock);
+ break;
- case STATE_DHCP_LEASED :
- ret = DHCP_RET_IP_LEASED;
+ case STATE_DHCP_LEASED :
+ ret = DHCP_RET_IP_LEASED;
if ((global_lease.lifetime != DHCP_INFINITY) && ((global_lease.lifetime/2) < dhcp_tick_1s)) {
debugf("> Maintains the IP address");
diff --git a/libdhcp/include/libdhcp/dhcp.h b/libdhcp/include/libdhcp/client.h
index 0b4c06f..fcff759 100644
--- a/libdhcp/include/libdhcp/dhcp.h
+++ b/libdhcp/include/libdhcp/client.h
@@ -1,4 +1,4 @@
-/* libdhcp/dhcp.h - A DHCP client
+/* libdhcp/client.h - A DHCP client
*
* Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -68,7 +68,7 @@
#define _LIBDHCP_DHCP_H_
#include <libhw/generic/net.h>
-#include "hw/w5500.h"
+#include <libhw/w5500.h>
enum dhcp_event {
DHCP_ASSIGN,
@@ -94,40 +94,12 @@ enum {
DHCP_RET_STOPPED // Stop processing DHCP protocol
};
-/*
- * @brief DHCP client initialization (outside of the main loop)
- * @param buf - buffer for processing DHCP message
- */
-void DHCP_init(void *buf);
-
-/*
- * @brief DHCP 1s Tick Timer handler
- * @note SHOULD BE register to your system 1s Tick timer handler
- */
-void DHCP_time_handler(void);
-
-/*
- * @brief DHCP client in the main loop
- * @return The value is as the follow \n
- * @ref DHCP_FAILED \n
- * @ref DHCP_RUNNING \n
- * @ref DHCP_IP_ASSIGN \n
- * @ref DHCP_IP_CHANGED \n
- * @ref DHCP_IP_LEASED \n
- * @ref DHCP_STOPPED \n
- *
- * @note This function is always called by you main task.
- */
-uint8_t DHCP_run(struct w5500 *chip, uint8_t socknum, dhcp_callback_t cb);
-//uint8_t DHCP_run(implements_net_packet_conn *sock, dhcp_callback_t cb);
-
-/*
- * @brief Stop DHCP processing
- * @note If you want to restart. call DHCP_init() and DHCP_run()
- */
-void DHCP_stop(implements_net_packet_conn *sock);
+COROUTINE dhcp_client_cr(struct w5500 *chip, uint8_t socknum,
+ struct net_eth_addr self_eth_addr,
+ char *self_hostname,
+ dhcp_callback_t cb);
-void xhandle(uint8_t opt_typ, uint8_t opt_len, uint8_t *opt_dat) {
+static void xhandle(uint8_t opt_typ, uint8_t opt_len, uint8_t *opt_dat) {
switch (opt_typ) {
case DHCP_OPT_SUBNET_MASK:
if (opt_len != 4)