diff options
Diffstat (limited to 'libdhcp')
-rw-r--r-- | libdhcp/dhcp_client.c | 91 | ||||
-rw-r--r-- | libdhcp/tests/test_client.c | 20 |
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"); } |