summaryrefslogtreecommitdiff
path: root/libdhcp/dhcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdhcp/dhcp.c')
-rw-r--r--libdhcp/dhcp.c710
1 files changed, 0 insertions, 710 deletions
diff --git a/libdhcp/dhcp.c b/libdhcp/dhcp.c
deleted file mode 100644
index 9786018..0000000
--- a/libdhcp/dhcp.c
+++ /dev/null
@@ -1,710 +0,0 @@
-/* libdhcp/dhcp.c - A DHCP client
- *
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-License-Identifier: AGPL-3.0-or-later
- *
- * -----------------------------------------------------------------------------
- * https://github.com/Wiznet/ioLibrary_Driver/blob/b981401e7f3d07015619adf44c13998e13e777f9/Internet/DHCP/dhcp.c
- *
- * Copyright (c) 2013, WIZnet Co., LTD.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the <ORGANIZATION> nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * -----------------------------------------------------------------------------
- * https://github.com/Wiznet/ioLibrary_Driver/blob/b981401e7f3d07015619adf44c13998e13e777f9/license.txt
- *
- * Copyright (c) 2014 WIZnet Co.,Ltd.
- * Copyright (c) WIZnet ioLibrary Project.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * SPDX-License-Identifier: MIT
- */
-
-#include <string.h> /* for strlen(), memcpy(), memset() */
-
-#include <libmisc/endian.h>
-#include <libmisc/vcall.h>
-#include <libdhcp/dhcp.h>
-
-/* Config *********************************************************************/
-
-#include "config.h"
-
-#ifndef CONFIG_DHCP_DEBUG
- #define CONFIG_DHCP_DEBUG 1
-#endif
-#ifndef CONFIG_DHCP_HOPS
- #define CONFIG_DHCP_HOPS 0
-#endif
-#ifndef CONFIG_DHCP_SECS
- #define CONFIG_DHCP_SECS 0
-#endif
-#ifndef CONFIG_DHCP_OPT_SIZE
- #define CONFIG_DHCP_OPT_SIZE 312
-#endif
-
-/* RFC 2131 definitions *******************************************************/
-
-/** https://datatracker.ietf.org/doc/html/rfc2131#page-9 */
-struct dhcp_msg {
- uint8_t op; /* DHCP_OP_{x} */
- uint8_t htype; /* DHCP_HTYPE_{x} */
- uint8_t hlen; /* length of ->chaddr (`sizeof(struct net_eth_addr)`) */
- uint8_t hops;
-
- uint32be_t xid; /* transaction ID */
-
- uint16be_t secs;
- uint16be_t flags; /* DHCP_FLAG_{x} */
-
- struct net_ip4_addr ciaddr; /* Request IP to DHCP sever */
- struct net_ip4_addr yiaddr; /* Offered IP from DHCP server */
- struct net_ip4_addr siaddr; /* next-server IP address (not used) */
- struct net_ip4_addr giaddr; /* relay-agent IP address (not used) */
- uint8_t chaddr[16]; /* client hardware (MAC) address */
- uint8_t sname[64]; /* server name (not used) */
- uint8_t file[128]; /* boot file name (not used) */
-
- uint8_t options[CONFIG_DHCP_OPT_SIZE];
-};
-static_assert(offsetof(struct dhcp_msg, options) == 236);
-#define DHCP_MSG_BASE_SIZE offsetof(struct dhcp_msg, options)
-
-/** https://datatracker.ietf.org/doc/html/rfc2131#page-10 */
-#define DHCP_OP_BOOTREQUEST 1
-#define DHCP_OP_BOOTREPLY 2
-
-/** https://datatracker.ietf.org/doc/html/rfc2131#page-11 */
-#define DHCP_FLAG_BROADCAST 0x8000
-
-/** https://datatracker.ietf.org/doc/html/rfc2131#section-3 */
-static const uint8_t dhcp_magic_cookie[] = {99, 130, 83, 99};
-
-/** https://datatracker.ietf.org/doc/html/rfc2131#section-3.3 */
-#define DHCP_INFINITY 0xffffffff
-
-/* IANA assignments ***********************************************************/
-
-/**
- * Port Numbers
- * https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
- */
-#define DHCP_PORT_SERVER ((uint16_t)67)
-#define DHCP_PORT_CLIENT ((uint16_t)68)
-
-/**
- * Hardware Types
- * https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml#arp-parameters-2
- */
-#define DHCP_HTYPE_ETHERNET ((uint8_t) 1)
-
-/**
- * DHCP Options
- * https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#options
- */
-#define DHCP_OPT_PAD ((uint8_t) 0) /* RFC2132: length: 0; meaning: None */
-#define DHCP_OPT_SUBNET_MASK ((uint8_t) 1) /* RFC2132: length: 4; meaning: Subnet Mask Value */
-#define DHCP_OPT_TIME_OFFSET ((uint8_t) 2) /* RFC2132: length: 4; meaning: Time Offset in Seconds from UTC (note: deprecated by 100 and 101 */
-#define DHCP_OPT_ROUTER ((uint8_t) 3) /* RFC2132: length: N; meaning: N/4 Router addresses */
-#define DHCP_OPT_TIME_SERVER ((uint8_t) 4) /* RFC2132: length: N; meaning: N/4 Timeserver addresses */
-#define DHCP_OPT_NAME_SERVER ((uint8_t) 5) /* RFC2132: length: N; meaning: N/4 IEN-116 Server addresses */
-#define DHCP_OPT_DOMAIN_SERVER ((uint8_t) 6) /* RFC2132: length: N; meaning: N/4 DNS Server addresses */
-#define DHCP_OPT_LOG_SERVER ((uint8_t) 7) /* RFC2132: length: N; meaning: N/4 Logging Server addresses */
-#define DHCP_OPT_QUOTES_SERVER ((uint8_t) 8) /* RFC2132: length: N; meaning: N/4 Quotes Server addresses */
-#define DHCP_OPT_LPR_SERVER ((uint8_t) 9) /* RFC2132: length: N; meaning: N/4 Printer Server addresses */
-#define DHCP_OPT_IMPRESS_SERVER ((uint8_t) 10) /* RFC2132: length: N; meaning: N/4 Impress Server addresses */
-#define DHCP_OPT_RLP_SERVER ((uint8_t) 11) /* RFC2132: length: N; meaning: N/4 RLP Server addresses */
-#define DHCP_OPT_HOSTNAME ((uint8_t) 12) /* RFC2132: length: N; meaning: Hostname string */
-#define DHCP_OPT_BOOT_FILE_SIZE ((uint8_t) 13) /* RFC2132: length: 2; meaning: Size of boot file in 512 byte chunks */
-#define DHCP_OPT_MERIT_DUMP_FILE ((uint8_t) 14) /* RFC2132: length: N; meaning: Client to dump and name the file to dump it to */
-#define DHCP_OPT_DOMAIN_NAME ((uint8_t) 15) /* RFC2132: length: N; meaning: The DNS domain name of the client */
-#define DHCP_OPT_SWAP_SERVER ((uint8_t) 16) /* RFC2132: length: N; meaning: Swap Server address */
-#define DHCP_OPT_ROOT_PATH ((uint8_t) 17) /* RFC2132: length: N; meaning: Path name for root disk */
-#define DHCP_OPT_EXTENSION_FILE ((uint8_t) 18) /* RFC2132: length: N; meaning: Path name for more BOOTP info */
-#define DHCP_OPT_FORWARD_ONOFF ((uint8_t) 19) /* RFC2132: length: 1; meaning: Enable/Disable IP Forwarding */
-#define DHCP_OPT_SRCRTE_ONOFF ((uint8_t) 20) /* RFC2132: length: 1; meaning: Enable/Disable Source Routing */
-#define DHCP_OPT_POLICY_FILTER ((uint8_t) 21) /* RFC2132: length: N; meaning: Routing Policy Filters */
-#define DHCP_OPT_MAX_DG_ASSEMBLY ((uint8_t) 22) /* RFC2132: length: 2; meaning: Max Datagram Reassembly Size */
-#define DHCP_OPT_DEFAULT_IP_TTL ((uint8_t) 23) /* RFC2132: length: 1; meaning: Default IP Time to Live */
-#define DHCP_OPT_MTU_TIMEOUT ((uint8_t) 24) /* RFC2132: length: 4; meaning: Path MTU Aging Timeout */
-#define DHCP_OPT_MTU_PLATEAU ((uint8_t) 25) /* RFC2132: length: N; meaning: Path MTU Plateau Table */
-#define DHCP_OPT_MTU_INTERFACE ((uint8_t) 26) /* RFC2132: length: 2; meaning: Interface MTU Size */
-#define DHCP_OPT_MTU_SUBNET ((uint8_t) 27) /* RFC2132: length: 1; meaning: All Subnets are Local */
-#define DHCP_OPT_BROADCAST_ADDRESS ((uint8_t) 28) /* RFC2132: length: 4; meaning: Broadcast Address */
-#define DHCP_OPT_MASK_DISCOVERY ((uint8_t) 29) /* RFC2132: length: 1; meaning: Perform Mask Discovery */
-#define DHCP_OPT_MASK_SUPPLIER ((uint8_t) 30) /* RFC2132: length: 1; meaning: Provide Mask to Others */
-#define DHCP_OPT_ROUTER_DISCOVERY ((uint8_t) 31) /* RFC2132: length: 1; meaning: Perform Router Discovery */
-#define DHCP_OPT_ROUTER_REQUEST ((uint8_t) 32) /* RFC2132: length: 4; meaning: Router Solicitation Address */
-#define DHCP_OPT_STATIC_ROUTE ((uint8_t) 33) /* RFC2132: length: N; meaning: Static Routing Table */
-#define DHCP_OPT_TRAILERS ((uint8_t) 34) /* RFC2132: length: 1; meaning: Trailer Encapsulation */
-#define DHCP_OPT_ARP_TIMEOUT ((uint8_t) 35) /* RFC2132: length: 4; meaning: ARP Cache Timeout */
-#define DHCP_OPT_ETHERNET ((uint8_t) 36) /* RFC2132: length: 1; meaning: Ethernet Encapsulation */
-#define DHCP_OPT_DEFAULT_TCP_TTL ((uint8_t) 37) /* RFC2132: length: 1; meaning: Default TCP Time to Live */
-#define DHCP_OPT_KEEPALIVE_TIME ((uint8_t) 38) /* RFC2132: length: 4; meaning: TCP Keepalive Interval */
-#define DHCP_OPT_KEEPALIVE_DATA ((uint8_t) 39) /* RFC2132: length: 1; meaning: TCP Keepalive Garbage */
-#define DHCP_OPT_NIS_DOMAIN ((uint8_t) 40) /* RFC2132: length: N; meaning: NIS Domain Name */
-#define DHCP_OPT_NIS_SERVERS ((uint8_t) 41) /* RFC2132: length: N; meaning: NIS Server Addresses */
-#define DHCP_OPT_NTP_SERVERS ((uint8_t) 42) /* RFC2132: length: N; meaning: NTP Server Addresses */
-#define DHCP_OPT_VENDOR_SPECIFIC ((uint8_t) 43) /* RFC2132: length: N; meaning: Vendor Specific Information */
-#define DHCP_OPT_NETBIOS_NAME_SRV ((uint8_t) 44) /* RFC2132: length: N; meaning: NETBIOS Name Servers */
-#define DHCP_OPT_NETBIOS_DIST_SRV ((uint8_t) 45) /* RFC2132: length: N; meaning: NETBIOS Datagram Distribution */
-#define DHCP_OPT_NETBIOS_NODE_TYPE ((uint8_t) 46) /* RFC2132: length: 1; meaning: NETBIOS Node Type */
-#define DHCP_OPT_NETBIOS_SCOPE ((uint8_t) 47) /* RFC2132: length: N; meaning: NETBIOS Scope */
-#define DHCP_OPT_X_WINDOW_FONT ((uint8_t) 48) /* RFC2132: length: N; meaning: X Window Font Server */
-#define DHCP_OPT_X_WINDOW_MANAGER ((uint8_t) 49) /* RFC2132: length: N; meaning: X Window Display Manager */
-#define DHCP_OPT_ADDRESS_REQUEST ((uint8_t) 50) /* RFC2132: length: 4; meaning: Requested IP Address */
-#define DHCP_OPT_ADDRESS_TIME ((uint8_t) 51) /* RFC2132: length: 4; meaning: IP Address Lease Time */
-#define DHCP_OPT_OVERLOAD ((uint8_t) 52) /* RFC2132: length: 1; meaning: Overload "sname" or "file */
-#define DHCP_OPT_DHCP_MSG_TYPE ((uint8_t) 53) /* RFC2132: length: 1; meaning: DHCP Message Type */
-#define DHCP_OPT_DHCP_SERVER_ID ((uint8_t) 54) /* RFC2132: length: 4; meaning: DHCP Server Identification */
-#define DHCP_OPT_PARAMETER_LIST ((uint8_t) 55) /* RFC2132: length: N; meaning: Parameter Request List */
-#define DHCP_OPT_DHCP_MESSAGE ((uint8_t) 56) /* RFC2132: length: N; meaning: DHCP Error Message */
-#define DHCP_OPT_DHCP_MAX_MSG_SIZE ((uint8_t) 57) /* RFC2132: length: 2; meaning: DHCP Maximum Message Size */
-#define DHCP_OPT_RENEWAL_TIME ((uint8_t) 58) /* RFC2132: length: 4; meaning: DHCP Renewal (T1) Time */
-#define DHCP_OPT_REBINDING_TIME ((uint8_t) 59) /* RFC2132: length: 4; meaning: DHCP Rebinding (T2) Time */
-#define DHCP_OPT_CLASS_ID ((uint8_t) 60) /* RFC2132: length: N; meaning: Class Identifier */
-#define DHCP_OPT_CLIENT_ID ((uint8_t) 61) /* RFC2132: length: N; meaning: Client Identifier */
-#define DHCP_OPT_END ((uint8_t)255) /* RFC2132: length: 0; meaning: None */
-
-/**
- * DHCP Message Type 53 Values
- * https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#message-type-53
- */
-#define DHCP_MSGTYP_DISCOVER ((uint8_t) 1) /* RFC2132 */
-#define DHCP_MSGTYP_OFFER ((uint8_t) 2) /* RFC2132 */
-#define DHCP_MSGTYP_REQUEST ((uint8_t) 3) /* RFC2132 */
-#define DHCP_MSGTYP_DECLINE ((uint8_t) 4) /* RFC2132 */
-#define DHCP_MSGTYP_ACK ((uint8_t) 5) /* RFC2132 */
-#define DHCP_MSGTYP_NAK ((uint8_t) 6) /* RFC2132 */
-#define DHCP_MSGTYP_RELEASE ((uint8_t) 7) /* RFC2132 */
-#define DHCP_MSGTYP_INFORM ((uint8_t) 8) /* RFC2132 */
-
-/* Implementation *************************************************************/
-
-#if CONFIG_DHCP_DEBUG
- #include <stdio.h>
- #define debugf(fmt, ...) printf(fmt "\n" __VA_OPT__(,) __VA_ARGS__)
-#else
- #define debugf(fmt, ...) ((void)0)
-#endif
-
-/* DHCP state machine. */
-#define STATE_DHCP_INIT 0 /* Initialize */
-#define STATE_DHCP_DISCOVER 1 /* send DISCOVER and wait OFFER */
-#define STATE_DHCP_REQUEST 2 /* send REQEUST and wait ACK or NACK */
-#define STATE_DHCP_LEASED 3 /* ReceiveD ACK and IP leased */
-#define STATE_DHCP_REREQUEST 4 /* send REQUEST for maintaining leased IP */
-#define STATE_DHCP_RELEASE 5 /* No use */
-#define STATE_DHCP_STOP 6 /* Stop processing DHCP */
-
-/* Global state. */
-struct net_ip4_addr DHCP_SIP; /* DHCP Server IP address */
-struct net_ip4_addr DHCP_REAL_SIP; /* For extract my DHCP server in a few DHCP server */
-struct net_ip4_addr OLD_allocated_ip = {0}; /* Previous IP address */
-struct dhcp_lease global_lease = {.lifetime = DHCP_INFINITY};
-int8_t dhcp_state = STATE_DHCP_INIT; /* DHCP state */
-int8_t dhcp_retry_count = 0;
-volatile uint32_t dhcp_tick_1s = 0; /* unit 1 second */
-uint32_t dhcp_tick_next = DHCP_WAIT_TIME ;
-char global_hostname[64];
-struct net_eth_addr global_eth_addr; /* DHCP Client MAC address. */
-
-#define mem_encode(dst, obj) ({ \
- typeof(obj) _obj = obj; \
- memcpy(dst, &_obj, sizeof(_obj)); \
- sizeof(_obj); \
-})
-
-static inline size_t str_encode(void *dst, char *str) {
- size_t len = strlen(str);
- memcpy(dst, str, len);
- return len;
-}
-
-/* make the common DHCP message */
-static inline void dhcp_msg_init(struct dhcp_msg *msg, size_t *optlen,
- struct net_eth_addr self_eth_addr,
- uint16_t flags, uint32_t xid) {
- size_t tmp;
-
- assert(msg);
- assert(optlen);
-
- *msg = (struct dhcp_msg){0};
-
- msg->op = DHCP_OP_BOOTREQUEST;
- msg->htype = DHCP_HTYPE_ETHERNET;
- msg->hlen = sizeof(self_eth_addr);
- msg->hops = CONFIG_DHCP_HOPS;
- msg->xid = uint32be_marshal(xid);
- msg->secs = uint16be_marshal(CONFIG_DHCP_SECS);
- msg->flags = uint16be_marshal(flags);
- msg->ciaddr = (struct net_ip4_addr){0};
- msg->yiaddr = (struct net_ip4_addr){0};
- msg->siaddr = (struct net_ip4_addr){0};
- msg->siaddr = (struct net_ip4_addr){0};
- msg->giaddr = (struct net_ip4_addr){0};
-
- tmp = mem_encode(msg->chaddr, self_eth_addr);
- memset(&msg->chaddr[tmp], 0, sizeof(msg->chaddr)-tmp);
-
- memset(msg->sname, 0, sizeof(msg->sname));
- memset(msg->file, 0, sizeof(msg->file));
-
- *optlen = 0;
- msg->options[*optlen++] = dhcp_magic_cookie[0];
- msg->options[*optlen++] = dhcp_magic_cookie[1];
- msg->options[*optlen++] = dhcp_magic_cookie[2];
- msg->options[*optlen++] = dhcp_magic_cookie[3];
-}
-
-static void dhcp_send_DISCOVER(implements_net_packet_conn *sock) {
- struct dhcp_msg msg;
- size_t k;
-
- dhcp_msg_init(&msg, &k, DHCP_FLAG_BROADCAST);
- DHCP_SIP = (struct net_ip4_addr){0};
- DHCP_REAL_SIP = (struct net_ip4_addr){0};
-
- /* Message type. */
- msg->options[k++] = DHCP_OPT_DHCP_MSG_TYPE;
- msg->options[k++] = 1;
- msg->options[k++] = DHCP_MSGTYP_DISCOVER;
-
- /* Our Client ID. */
- msg->options[k++] = DHCP_OPT_CLIENT_ID;
- msg->options[k++] = 1+sizeof(self_eth_addr);
- msg->options[k++] = DHCP_HTYPE_ETHERNET;
- k += mem_encode(&msg->options[k], self_eth_addr);
-
- /* Our requested hostname. */
- msg->options[k++] = DHCP_OPT_HOSTNAME;
- msg->options[k++] = strlen(global_hostname);
- k += str_encode(&msg->options[k], global_hostname);
-
- /* Which parameters we want back. */
- msg->options[k++] = DHCP_OPT_PARAMETER_LIST;
- msg->options[k++] = 6;
- msg->options[k++] = DHCP_OPT_SUBNET_MASK; /* 1 */
- msg->options[k++] = DHCP_OPT_ROUTER; /* 2 */
- msg->options[k++] = DHCP_OPT_DOMAIN_SERVER; /* 3 */
- msg->options[k++] = DHCP_OPT_DOMAIN_NAME; /* 4 */
- msg->options[k++] = DHCP_OPT_RENEWAL_TIME; /* 5 */
- msg->options[k++] = DHCP_OPT_REBINDING_TIME; /* 6 */
-
- /* End. */
- msg->options[k++] = DHCP_OPT_END;
- assert(k <= CONFIG_DHCP_OPT_SIZE);
-
- /* Send. */
- debugf("> Send DHCP_DISCOVER");
- VCALL(sock, sendto, msg, DHCP_MSG_BASE_SIZE + k, net_ip4_addr_broadcast, DHCP_PORT_SERVER);
-}
-
-static void dhcp_send_REQUEST(implements_net_packet_conn *sock) {
- struct net_ip4_addr ip;
- struct dhcp_msg msg;
- size_t k;
-
- dhcp_msg_init(msg, &k,
- (dhcp_state != STATE_DHCP_LEASED && dhcp_state != STATE_DHCP_REREQUEST) ? DHCP_FLAG_BROADCAST : 0);
-
- switch (dhcp_state) {
- case STATE_DHCP_LEASED:
- case STATE_DHCP_REREQUEST:
- msg->ciaddr = global_lease.addr;
- ip = DHCP_SIP;
- break;
- default:
- ip = net_ip4_addr_broadcast;
- }
-
- /* Message type. */
- msg->options[k++] = DHCP_OPT_DHCP_MSG_TYPE;
- msg->options[k++] = 1;
- msg->options[k++] = DHCP_MSGTYP_REQUEST;
-
- /* Our Client ID. */
- msg->options[k++] = DHCP_OPT_CLIENT_ID;
- msg->options[k++] = 1+sizeof(self_eth_addr);
- msg->options[k++] = DHCP_HTYPE_ETHERNET;
- k += mem_encode(&msg->options[k], self_eth_addr);
-
- switch (dhcp_state) {
- case STATE_DHCP_LEASED:
- case STATE_DHCP_REREQUEST:
- /* Our current IP address. */
- msg->options[k++] = DHCP_OPT_ADDRESS_REQUEST;
- msg->options[k++] = sizeof(global_lease.addr);
- k += mem_encode(&msg->options[k], global_lease.addr);
-
- /* The server we got it from. */
- msg->options[k++] = DHCP_OPT_DHCP_SERVER_ID;
- msg->options[k++] = sizeof(DHCP_SIP);
- k += mem_encode(&msg->options[k], DHCP_SIP);
- }
-
- /* Our requested hostname. */
- msg->options[k++] = DHCP_OPT_HOSTNAME;
- msg->options[k++] = strlen(global_hostname);
- k += str_encode(&msg->options[k], global_hostname);
-
- /* Which parameters we want back. */
- msg->options[k++] = DHCP_OPT_PARAMETER_LIST;
- msg->options[k++] = 8;
- msg->options[k++] = DHCP_OPT_SUBNET_MASK; /* 1 */
- msg->options[k++] = DHCP_OPT_ROUTER; /* 2 */
- msg->options[k++] = DHCP_OPT_DOMAIN_SERVER; /* 3 */
- msg->options[k++] = DHCP_OPT_DOMAIN_NAME; /* 4 */
- msg->options[k++] = DHCP_OPT_RENEWAL_TIME; /* 5 */
- msg->options[k++] = DHCP_OPT_REBINDING_TIME; /* 6 */
- msg->options[k++] = DHCP_OPT_ROUTER_DISCOVERY; /* 7 */
- msg->options[k++] = DHCP_OPT_STATIC_ROUTE; /* 8 */
-
- /* End. */
- msg->options[k++] = DHCP_OPT_END;
- assert(k <= CONFIG_DHCP_OPT_SIZE);
-
- debugf("> Send DHCP_REQUEST");
- VCALL(sock, sendto, msg, DHCP_MSG_BASE_SIZE + k, ip, DHCP_PORT_SERVER);
-}
-
-static void dhcp_send_DECLINE(implements_net_packet_conn *sock) {
- size_t k;
-
- dhcp_msg_init(pDHCPMSG, &k, DHCP_FLAG_BROADCAST);
- pDHCPMSG->flags = uint16be_marshal(0);
-
- /* Option Request Param. */
- pDHCPMSG->options[k++] = DHCP_OPT_DHCP_MSG_TYPE;
- pDHCPMSG->options[k++] = 1;
- pDHCPMSG->options[k++] = DHCP_MSGTYP_DECLINE;
-
- /* Our Client ID. */
- pDHCPMSG->options[k++] = DHCP_OPT_CLIENT_ID;
- pDHCPMSG->options[k++] = 1+sizeof(self_eth_addr);
- pDHCPMSG->options[k++] = DHCP_HTYPE_ETHERNET;
- memcpy(&pDHCPMSG->options[k], self_eth_addr.octets, sizeof(self_eth_addr));
- k += sizeof(self_eth_addr);
-
- /* Our current IP address. */
- pDHCPMSG->options[k++] = DHCP_OPT_ADDRESS_REQUEST;
- pDHCPMSG->options[k++] = sizeof(global_lease.addr);
- k += mem_encode(&pDHCPMSG->options[k], global_lease.addr);
-
- /* The server we got it from. */
- pDHCPMSG->options[k++] = DHCP_OPT_DHCP_SERVER_ID;
- pDHCPMSG->options[k++] = sizeof(DHCP_SIP);
- k += mem_encode(&pDHCPMSG->options[k], DHCP_SIP);
-
- /* End. */
- pDHCPMSG->options[k++] = DHCP_OPT_END;
-
- debugf("> Send DHCP_DECLINE");
- assert(k <= CONFIG_DHCP_OPT_SIZE);
- 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) {
- struct net_ip4_addr srv_addr;
- uint16_t srv_port;
- size_t msg_len;
- msg_len = VCALL(sock, recvfrom, pDHCPMSG, sizeof(*pDHCPMSG), &srv_addr, &srv_port);
- 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;
- }
- /* 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;
- }
- /* 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;
- }
- }
-
- uint8_t msg_type = 0;
- for (size_t k = 4, k_max = msg_len - DHCP_MSG_BASE_SIZE, opt_len; k < k_max; k += opt_len) {
- uint8_t opt_typ;
- opt_typ = pDHCPMSG->options[k++];
- switch (opt_typ) {
- case DHCP_OPT_END:
- opt_len = k_max - k;
- break;
- case DHCP_OPT_PAD:
- opt_len = 0;
- break;
- default:
- opt_len = pDHCPMSG->options[k++];
- xhandle(opt_typ, opt_len, &pDHCPMSG->options[k]);
- }
- switch (opt_typ) {
- case DHCP_OPT_DHCP_MSG_TYPE:
- if (opt_len != 1)
- continue;
- msg_type = pDHCPMSG->options[k];
- break;
- case DHCP_OPT_ADDRESS_TIME:
- if (opt_len != 4)
- continue;
- global_lease.lifetime = uint32be_decode(&pDHCPMSG->options[k]);
-#if CONFIG_DHCP_DEBUG
- global_lease.lifetime = 10;
-#endif
- break;
- case DHCP_OPT_DHCP_SERVER_ID:
- if (opt_len != 4)
- continue;
- DHCP_SIP.octets[0] = pDHCPMSG->options[k+0];
- DHCP_SIP.octets[1] = pDHCPMSG->options[k+1];
- DHCP_SIP.octets[2] = pDHCPMSG->options[k+2];
- DHCP_SIP.octets[3] = pDHCPMSG->options[k+3];
- DHCP_REAL_SIP = srv_addr;
- break;
- }
- }
- return msg_type;
-}
-
-static void dhcp_reset_timeout(void) {
- dhcp_tick_1s = 0;
- dhcp_tick_next = DHCP_WAIT_TIME;
- dhcp_retry_count = 0;
-}
-
-static uint8_t dhcp_check_timeout(implements_net_packet_conn *sock) {
- uint8_t ret = DHCP_RET_RUNNING;
-
- if (dhcp_retry_count < MAX_DHCP_RETRY) {
- if (dhcp_tick_next < dhcp_tick_1s) {
-
- switch ( dhcp_state ) {
- case STATE_DHCP_DISCOVER :
- /*debugf("<<timeout>> state : STATE_DHCP_DISCOVER");*/
- dhcp_send_DISCOVER(sock);
- break;
-
- case STATE_DHCP_REQUEST :
- /*debugf("<<timeout>> state : STATE_DHCP_REQUEST");*/
- dhcp_send_REQUEST(sock);
- break;
-
- case STATE_DHCP_REREQUEST :
- /*debugf("<<timeout>> state : STATE_DHCP_REREQUEST");*/
- dhcp_send_REQUEST(sock);
- break;
-
- default :
- break;
- }
-
- dhcp_tick_1s = 0;
- dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME;
- dhcp_retry_count++;
- }
- } else { /* timeout occurred */
-
- switch(dhcp_state) {
- case STATE_DHCP_DISCOVER:
- dhcp_state = STATE_DHCP_INIT;
- ret = DHCP_RET_FAILED;
- break;
- case STATE_DHCP_REQUEST:
- case STATE_DHCP_REREQUEST:
- dhcp_send_DISCOVER(sock);
- dhcp_state = STATE_DHCP_DISCOVER;
- break;
- default :
- break;
- }
- dhcp_reset_timeout();
- }
- return ret;
-}
-
-static int8_t dhcp_check_leasedIP(implements_net_packet_conn *sock) {
- int32_t ret;
-
- /* IP conflict detection : ARP request - ARP reply */
- /* Broadcasting ARP Request for check the IP conflict using UDP sendto() function */
- ret = VCALL(sock, sendto, "CHECK_IP_CONFLICT", 17, global_lease.addr, 5000);
-
- if (ret == NET_ETIMEDOUT) {
- /* UDP send Timeout occurred : allocated IP address is unique, DHCP Success */
- debugf("\r\n> Check leased IP - OK");
- return 1;
- }
-
- /* Received ARP reply or etc : IP address conflict occur, DHCP Failed */
- dhcp_send_DECLINE(sock);
-
- ret = dhcp_tick_1s;
- while ((dhcp_tick_1s - ret) < 2) {} /* wait for 1s over; wait to complete to send DECLINE message; */
-
- 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) {
- uint32_t xid;
- implements_net_packet_conn *sock;
-
- xid = 0x12345678;
- xid += self_eth_addr.octets[3];
- xid += self_eth_addr.octets[4];
- xid += self_eth_addr.octets[5];
- xid += (self_eth_addr.octets[3] ^
- self_eth_addr.octets[4] ^
- self_eth_addr.octets[5]);
-
- 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);
-
- 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_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_reset_timeout();
-
- dhcp_state = STATE_DHCP_DISCOVER;
- } else
- ret = dhcp_check_timeout(sock);
- break;
-
- 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");
-
- msg_type = 0;
- OLD_allocated_ip = global_lease.addr;
-
- xid++;
-
- dhcp_send_REQUEST(sock);
-
- dhcp_reset_timeout();
-
- dhcp_state = STATE_DHCP_REREQUEST;
- }
- break;
-
- case STATE_DHCP_REREQUEST :
- ret = DHCP_RET_IP_LEASED;
- if (msg_type == DHCP_MSGTYP_ACK) {
- dhcp_retry_count = 0;
- if (memcmp(OLD_allocated_ip.octets, global_lease.addr.octets, sizeof(global_lease.addr))) {
- ret = DHCP_RET_IP_CHANGED;
- cb(DHCP_UPDATE, global_lease);
- debugf(">IP changed.");
- } else {
- debugf(">IP is continued.");
- }
- dhcp_reset_timeout();
- dhcp_state = STATE_DHCP_LEASED;
- } else if (msg_type == DHCP_MSGTYP_NAK) {
- debugf("> Receive DHCP_NACK, Failed to maintain ip");
- dhcp_reset_timeout();
-
- dhcp_state = STATE_DHCP_DISCOVER;
- } else
- ret = dhcp_check_timeout(sock);
- break;
- default :
- break;
- }
-
- return ret;
-}