summaryrefslogtreecommitdiff
path: root/libdhcp/dhcp_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdhcp/dhcp_client.c')
-rw-r--r--libdhcp/dhcp_client.c91
1 files changed, 40 insertions, 51 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: