diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-11-04 12:49:09 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-11-04 12:49:15 -0700 |
commit | ea73a6242446f33951e5daa342e827bef700b835 (patch) | |
tree | 041e0563189ef7502ba61e96aeb344ce927c946d | |
parent | 3c81186daf97cf7011fd2806dfd0bc3b875e92f3 (diff) |
wip dhcplukeshu/dhcp
-rw-r--r-- | cmd/sbc_harness/CMakeLists.txt | 2 | ||||
-rw-r--r-- | cmd/sbc_harness/main.c | 4 | ||||
-rw-r--r-- | libdhcp/CMakeLists.txt | 2 | ||||
-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 |
5 files changed, 84 insertions, 89 deletions
diff --git a/cmd/sbc_harness/CMakeLists.txt b/cmd/sbc_harness/CMakeLists.txt index 2018cf7..25485a6 100644 --- a/cmd/sbc_harness/CMakeLists.txt +++ b/cmd/sbc_harness/CMakeLists.txt @@ -19,7 +19,7 @@ target_link_libraries(sbc_harness_objs libmisc libusb - #libdhcp + libdhcp libhw ) pico_enable_stdio_usb(sbc_harness_objs 0) diff --git a/cmd/sbc_harness/main.c b/cmd/sbc_harness/main.c index b9c5330..610725f 100644 --- a/cmd/sbc_harness/main.c +++ b/cmd/sbc_harness/main.c @@ -15,6 +15,7 @@ #include <libhw/w5500.h> #include <libmisc/hash.h> #include <libusb/usb_common.h> +#include <libdhcp/client.h> #include "usb_keyboard.h" @@ -80,8 +81,9 @@ int main() { usb_keyboard_rpc_t keyboard_chan = {0}; coroutine_add(usb_keyboard_cr, &keyboard_chan); //coroutine_add(hello_world_cr, &keyboard_chan); - //coroutine_add(dhcp_client_cr, NULL); + coroutine_add(dhcp_client_cr, NULL); /* event loop *********************************************************/ + printf("main\n"); coroutine_main(); } 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) |