summaryrefslogtreecommitdiff
path: root/libdhcp
diff options
context:
space:
mode:
Diffstat (limited to 'libdhcp')
-rw-r--r--libdhcp/dhcp_client.c91
-rw-r--r--libdhcp/tests/test_client.c20
2 files changed, 50 insertions, 61 deletions
diff --git a/libdhcp/dhcp_client.c b/libdhcp/dhcp_client.c
index 57a2f60..1164355 100644
--- a/libdhcp/dhcp_client.c
+++ b/libdhcp/dhcp_client.c
@@ -252,11 +252,8 @@ static inline enum requirement dhcp_table5(typeof((struct dhcp_client){}.state)
* @param client->lease_client_addr (sometimes)
* @param client->lease_server_id (sometimes)
* @param client->sock
- *
- * @return client->last_sent_msgtyp
- * @return whether there was an error
*/
-static bool dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const char *errstr, struct dhcp_msg *scratch_msg) {
+static error dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const char *errstr, struct dhcp_msg *scratch_msg) {
/**********************************************************************\
* Preconditions *
\**********************************************************************/
@@ -462,14 +459,14 @@ static bool dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const c
* Send *
\**********************************************************************/
log_debugln("state ", state_strs[client->state], ": sending DHCP ", dhcp_msgtyp_str(msgtyp));
- ssize_t r = LO_CALL(client->sock, sendto, scratch_msg, DHCP_MSG_BASE_SIZE + optlen,
- client_broadcasts ? net_ip4_addr_broadcast : client->lease_server_id, DHCP_PORT_SERVER);
- if (r < 0) {
- log_debugln("error: sendto: ", r);
- return true;
+ error err = LO_CALL(client->sock, sendto, scratch_msg, DHCP_MSG_BASE_SIZE + optlen,
+ client_broadcasts ? net_ip4_addr_broadcast : client->lease_server_id, DHCP_PORT_SERVER);
+ if (!ERROR_IS_NULL(err)) {
+ log_debugln("error: sendto: ", (error, err));
+ return err;
}
client->last_sent_msgtyp = msgtyp;
- return false;
+ return ERROR_NULL;
}
struct dhcp_recv_msg {
@@ -565,24 +562,20 @@ static inline enum requirement dhcp_table3(uint8_t req_msgtyp, uint8_t resp_msgt
* @param client->self_eth_addr
* @param client->xid
* @param client->lease_server_id
- *
- * @return
- * - <0: -errno
- * - 0: success
- * - >0: should not happen
*/
-static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg *ret) {
+static error dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg *ret) {
struct net_ip4_addr srv_addr;
uint16_t srv_port;
- ssize_t msg_len;
+ size_t msg_len;
assert(client);
ignore:
- msg_len = LO_CALL(client->sock, recvfrom, &ret->raw, sizeof(ret->raw), &srv_addr, &srv_port);
- if (msg_len < 0)
+ size_t_or_error r = LO_CALL(client->sock, recvfrom, &ret->raw, sizeof(ret->raw), &srv_addr, &srv_port);
+ if (r.is_err)
/* msg_len is -errno */
- return msg_len;
+ return r.err;
+ msg_len = r.size_t;
/* Validate L3: IP */
/* Don't validate that srv_addr matches client->server_id
@@ -595,10 +588,10 @@ static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg
goto ignore;
/* Validate L5: DHCP. */
- if ((size_t)msg_len < DHCP_MSG_BASE_SIZE + sizeof(dhcp_magic_cookie))
+ if (msg_len < DHCP_MSG_BASE_SIZE + sizeof(dhcp_magic_cookie))
/* ignore impossibly short message */
goto ignore;
- if ((size_t)msg_len > sizeof(ret->raw))
+ if (msg_len > sizeof(ret->raw))
/* ignore message that is larger than the specified
* DHCP_OPT_DHCP_MAX_MSG_SIZE */
goto ignore;
@@ -698,7 +691,7 @@ static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg
goto ignore;
}
- return 0;
+ return ERROR_NULL;
}
static void dhcp_client_take_lease(struct dhcp_client *client, struct dhcp_recv_msg *msg, bool ifup) {
@@ -748,18 +741,19 @@ static void dhcp_client_take_lease(struct dhcp_client *client, struct dhcp_recv_
static void dhcp_client_setstate(struct dhcp_client *client,
typeof((struct dhcp_client){}.state) newstate,
uint8_t send_msgtyp, const char *errstr, struct dhcp_recv_msg *scratch_msg) {
- if (send_msgtyp)
- (void)dhcp_client_send(client, send_msgtyp, errstr, &scratch_msg->raw);
+ if (send_msgtyp) {
+ error err = dhcp_client_send(client, send_msgtyp, errstr, &scratch_msg->raw);
+ error_cleanup(&err);
+ }
client->state = newstate;
}
[[noreturn]] static void dhcp_client_run(struct dhcp_client *client, struct dhcp_recv_msg *scratch_msg) {
assert(client);
- ssize_t r;
-
/* State transition diagram: https://datatracker.ietf.org/doc/html/rfc2131#page-35 */
for (;;) {
+ [[gnu::cleanup(error_cleanup)]] error err = {};
log_debugln("loop: state=", state_strs[client->state]);
switch (client->state) {
case STATE_INIT:
@@ -769,8 +763,8 @@ static void dhcp_client_setstate(struct dhcp_client *client,
break;
case STATE_SELECTING:
LO_CALL(client->sock, set_recv_deadline, client->time_ns_init+CONFIG_DHCP_SELECTING_NS);
- switch ((r = dhcp_client_recv(client, scratch_msg))) {
- case 0:
+ LM_PARTIAL_SWITCH ((err = dhcp_client_recv(client, scratch_msg)).num) {
+ case E_NOERROR:
switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
case DHCP_MSGTYP_OFFER:
/* Accept the first offer. */
@@ -781,18 +775,17 @@ static void dhcp_client_setstate(struct dhcp_client *client,
/* ignore */
}
break;
- case -NET_ERECV_TIMEOUT:
+ case E_NET_ERECV_TIMEOUT:
dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
break;
default:
- assert(r < 0);
- log_debugln("error: recvfrom: ", r);
+ log_debugln("error: recvfrom: ", (error, err));
}
break;
case STATE_REQUESTING:
LO_CALL(client->sock, set_recv_deadline, 0);
- switch ((r = dhcp_client_recv(client, scratch_msg))) {
- case 0:
+ LM_PARTIAL_SWITCH ((err = dhcp_client_recv(client, scratch_msg)).num) {
+ case E_NOERROR:
switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
case DHCP_MSGTYP_NAK:
dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
@@ -811,22 +804,20 @@ static void dhcp_client_setstate(struct dhcp_client *client,
}
break;
default:
- assert(r < 0);
- log_debugln("error: recvfrom: ", r);
+ log_debugln("error: recvfrom: ", (error, err));
}
break;
case STATE_BOUND:
LO_CALL(client->sock, set_recv_deadline, client->lease_time_ns_t1);
- switch ((r = dhcp_client_recv(client, scratch_msg))) {
- case 0:
+ LM_PARTIAL_SWITCH ((err = dhcp_client_recv(client, scratch_msg)).num) {
+ case E_NOERROR:
/* discard */
break;
- case -NET_ERECV_TIMEOUT:
+ case E_NET_ERECV_TIMEOUT:
dhcp_client_setstate(client, STATE_RENEWING, DHCP_MSGTYP_REQUEST, NULL, scratch_msg);
break;
default:
- assert(r < 0);
- log_debugln("error: recvfrom: ", r);
+ log_debugln("error: recvfrom: ", (error, err));
}
break;
case STATE_RENEWING:
@@ -834,8 +825,8 @@ static void dhcp_client_setstate(struct dhcp_client *client,
client->time_ns_init = LO_CALL(bootclock, get_time_ns);
LO_CALL(client->sock, set_recv_deadline, client->lease_time_ns_t2);
- switch ((r = dhcp_client_recv(client, scratch_msg))) {
- case 0:
+ LM_PARTIAL_SWITCH ((err = dhcp_client_recv(client, scratch_msg)).num) {
+ case E_NOERROR:
switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
case DHCP_MSGTYP_NAK:
LO_CALL(client->iface, ifdown);
@@ -849,19 +840,18 @@ static void dhcp_client_setstate(struct dhcp_client *client,
/* ignore */
}
break;
- case -NET_ERECV_TIMEOUT:
+ case E_NET_ERECV_TIMEOUT:
client->lease_server_id = net_ip4_addr_zero;
dhcp_client_setstate(client, STATE_REBINDING, DHCP_MSGTYP_REQUEST, NULL, scratch_msg);
break;
default:
- assert(r < 0);
- log_debugln("error: recvfrom: ", r);
+ log_debugln("error: recvfrom: ", (error, err));
}
break;
case STATE_REBINDING:
LO_CALL(client->sock, set_recv_deadline, client->lease_time_ns_end);
- switch ((r = dhcp_client_recv(client, scratch_msg))) {
- case 0:
+ LM_PARTIAL_SWITCH ((err = dhcp_client_recv(client, scratch_msg)).num) {
+ case E_NOERROR:
switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
case DHCP_MSGTYP_NAK:
LO_CALL(client->iface, ifdown);
@@ -875,13 +865,12 @@ static void dhcp_client_setstate(struct dhcp_client *client,
/* ignore */
}
break;
- case -NET_ERECV_TIMEOUT:
+ case E_NET_ERECV_TIMEOUT:
LO_CALL(client->iface, ifdown);
dhcp_client_setstate(client, STATE_BOUND, 0, NULL, scratch_msg);
break;
default:
- assert(r < 0);
- log_debugln("error: recvfrom: ", r);
+ log_debugln("error: recvfrom: ", (error, err));
}
break;
case STATE_INIT_REBOOT:
diff --git a/libdhcp/tests/test_client.c b/libdhcp/tests/test_client.c
index 09557e5..cf76653 100644
--- a/libdhcp/tests/test_client.c
+++ b/libdhcp/tests/test_client.c
@@ -23,14 +23,14 @@ LO_IMPLEMENTATION_C(io_closer, struct test_udp, test_udp, static);
LO_IMPLEMENTATION_H(net_packet_conn, struct test_udp, test_udp);
LO_IMPLEMENTATION_C(net_packet_conn, struct test_udp, test_udp, static);
-static ssize_t test_udp_sendto(struct test_udp *LM_UNUSED(self), void *LM_UNUSED(buf), size_t len, struct net_ip4_addr LM_UNUSED(node), uint16_t LM_UNUSED(port)) {
+static error test_udp_sendto(struct test_udp *LM_UNUSED(self), void *LM_UNUSED(buf), size_t LM_UNUSED(len), struct net_ip4_addr LM_UNUSED(node), uint16_t LM_UNUSED(port)) {
static unsigned cnt = 0;
if (cnt++ % 2 == 0)
- return -NET_EOTHER;
- return len;
+ return error_new(E_EUNKNOWN);
+ return ERROR_NULL;
}
-static ssize_t test_udp_recvfrom(struct test_udp *LM_UNUSED(self), void *buf, size_t len, struct net_ip4_addr *ret_node, uint16_t *ret_port) {
+static size_t_or_error test_udp_recvfrom(struct test_udp *LM_UNUSED(self), void *buf, size_t len, struct net_ip4_addr *ret_node, uint16_t *ret_port) {
static const uint8_t resp_offer[] = {0x02,0x01,0x06,0x00,0xE8,0x40,0xC6,0x79,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0xC0,0xA8,0x0A,0x78,0xC0,0xA8,0x0A,0x01,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x82,0x53,0x63,0x35,0x01,0x02,0x36,0x04,0xC0,0xA8,0x0A,0x01,0x33,0x04,0x00,0x00,0xA8,0xC0,0x3A,0x04,0x00,0x00,0x54,0x60,0x3B,0x04,0x00,0x00,0x93,0xA8,0x01,0x04,0xFF,0xFF,0xFF,0x00,0x1C,0x04,0xC0,0xA8,0x0A,0xFF,0x03,0x04,0xC0,0xA8,0x0A,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
static const uint8_t resp_ack[] = {0x02,0x01,0x06,0x00,0xE8,0x40,0xC6,0x79,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0xC0,0xA8,0x0A,0x78,0xC0,0xA8,0x0A,0x01,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x82,0x53,0x63,0x35,0x01,0x05,0x36,0x04,0xC0,0xA8,0x0A,0x01,0x33,0x04,0x00,0x00,0xA8,0xC0,0x3A,0x04,0x00,0x00,0x54,0x60,0x3B,0x04,0x00,0x00,0x93,0xA8,0x01,0x04,0xFF,0xFF,0xFF,0x00,0x1C,0x04,0xC0,0xA8,0x0A,0xFF,0x03,0x04,0xC0,0xA8,0x0A,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
@@ -38,24 +38,24 @@ static ssize_t test_udp_recvfrom(struct test_udp *LM_UNUSED(self), void *buf, si
const void *resp;
size_t resp_len;
switch (cnt++) {
- case 0: return -NET_EOTHER;
+ case 0: return ERROR_NEW_ERR(size_t, error_new(E_EUNKNOWN));
case 1: resp = resp_offer; resp_len = sizeof(resp_offer); break;
- case 2: return -NET_EOTHER;
+ case 2: return ERROR_NEW_ERR(size_t, error_new(E_EUNKNOWN));
case 3: resp = resp_ack; resp_len = sizeof(resp_ack); break;
- default: return -NET_ERECV_TIMEOUT;
+ default: return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT));
}
test_assert(len >= resp_len);
memcpy(buf, resp, resp_len);
*ret_node = ((struct net_ip4_addr){{192,168,10,1}});
*ret_port = 67;
- return resp_len;
+ return ERROR_NEW_VAL(size_t, resp_len);
}
static void test_udp_set_recv_deadline(struct test_udp *LM_UNUSED(self), uint64_t LM_UNUSED(ns_since_boot)) {
/* Do nothing? */
}
-static int test_udp_close(struct test_udp *LM_UNUSED(self)) {
+static error test_udp_close(struct test_udp *LM_UNUSED(self)) {
assert_notreached("not implemented");
}
@@ -90,7 +90,7 @@ static lo_interface net_stream_listener test_tcp_listen(struct test_iface *LM_UN
assert_notreached("not implemented");
}
-static lo_interface net_stream_conn test_tcp_dial(struct test_iface *LM_UNUSED(self), struct net_ip4_addr LM_UNUSED(remote_node), uint16_t LM_UNUSED(remote_port)) {
+static net_stream_conn_or_error test_tcp_dial(struct test_iface *LM_UNUSED(self), struct net_ip4_addr LM_UNUSED(remote_node), uint16_t LM_UNUSED(remote_port)) {
assert_notreached("not implemented");
}