mirror of
https://github.com/systemd/systemd.git
synced 2024-11-07 09:56:51 +03:00
dhcp: Add timeout and main loop support
Require a main loop to be set when creating a DHCP client. Set up a timer to resend DHCP Discover messages and add a 0-2 second delay to the timeout value. Move to state Selecting after successful sending of a Discover message.
This commit is contained in:
parent
117539f8b7
commit
d3d8ac2f2b
@ -34,12 +34,15 @@
|
|||||||
|
|
||||||
struct sd_dhcp_client {
|
struct sd_dhcp_client {
|
||||||
DHCPState state;
|
DHCPState state;
|
||||||
|
sd_event *event;
|
||||||
|
sd_event_source *timeout_resend;
|
||||||
int index;
|
int index;
|
||||||
uint8_t *req_opts;
|
uint8_t *req_opts;
|
||||||
size_t req_opts_size;
|
size_t req_opts_size;
|
||||||
uint32_t last_addr;
|
uint32_t last_addr;
|
||||||
struct ether_addr mac_addr;
|
struct ether_addr mac_addr;
|
||||||
uint32_t xid;
|
uint32_t xid;
|
||||||
|
usec_t start_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t default_req_opts[] = {
|
static const uint8_t default_req_opts[] = {
|
||||||
@ -125,6 +128,8 @@ static int client_stop(sd_dhcp_client *client, int error)
|
|||||||
assert_return(client->state != DHCP_STATE_INIT &&
|
assert_return(client->state != DHCP_STATE_INIT &&
|
||||||
client->state != DHCP_STATE_INIT_REBOOT, -EALREADY);
|
client->state != DHCP_STATE_INIT_REBOOT, -EALREADY);
|
||||||
|
|
||||||
|
client->timeout_resend = sd_event_source_unref(client->timeout_resend);
|
||||||
|
|
||||||
switch (client->state) {
|
switch (client->state) {
|
||||||
|
|
||||||
case DHCP_STATE_INIT:
|
case DHCP_STATE_INIT:
|
||||||
@ -278,8 +283,61 @@ static int client_send_discover(sd_dhcp_client *client, uint16_t secs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int client_timeout_resend(sd_event_source *s, uint64_t usec,
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
|
sd_dhcp_client *client = userdata;
|
||||||
|
usec_t next_timeout;
|
||||||
|
uint16_t secs;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
switch (client->state) {
|
||||||
|
case DHCP_STATE_INIT:
|
||||||
|
case DHCP_STATE_SELECTING:
|
||||||
|
|
||||||
|
if (!client->start_time)
|
||||||
|
client->start_time = usec;
|
||||||
|
|
||||||
|
secs = (usec - client->start_time) / USEC_PER_SEC;
|
||||||
|
|
||||||
|
next_timeout = usec + 2 * USEC_PER_SEC + (random() & 0x1fffff);
|
||||||
|
|
||||||
|
err = sd_event_add_monotonic(client->event, next_timeout,
|
||||||
|
10 * USEC_PER_MSEC,
|
||||||
|
client_timeout_resend, client,
|
||||||
|
&client->timeout_resend);
|
||||||
|
if (err < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (client_send_discover(client, secs) >= 0)
|
||||||
|
client->state = DHCP_STATE_SELECTING;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DHCP_STATE_INIT_REBOOT:
|
||||||
|
case DHCP_STATE_REBOOTING:
|
||||||
|
case DHCP_STATE_REQUESTING:
|
||||||
|
case DHCP_STATE_BOUND:
|
||||||
|
case DHCP_STATE_RENEWING:
|
||||||
|
case DHCP_STATE_REBINDING:
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
client_stop(client, err);
|
||||||
|
|
||||||
|
/* Errors were dealt with when stopping the client, don't spill
|
||||||
|
errors into the event loop handler */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int sd_dhcp_client_start(sd_dhcp_client *client)
|
int sd_dhcp_client_start(sd_dhcp_client *client)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
assert_return(client, -EINVAL);
|
assert_return(client, -EINVAL);
|
||||||
assert_return(client->index >= 0, -EINVAL);
|
assert_return(client->index >= 0, -EINVAL);
|
||||||
assert_return(client->state == DHCP_STATE_INIT ||
|
assert_return(client->state == DHCP_STATE_INIT ||
|
||||||
@ -287,7 +345,18 @@ int sd_dhcp_client_start(sd_dhcp_client *client)
|
|||||||
|
|
||||||
client->xid = random_u();
|
client->xid = random_u();
|
||||||
|
|
||||||
return client_send_discover(client, 0);
|
err = sd_event_add_monotonic(client->event, now(CLOCK_MONOTONIC), 0,
|
||||||
|
client_timeout_resend, client,
|
||||||
|
&client->timeout_resend);
|
||||||
|
if (err < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
client_stop(client, err);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sd_dhcp_client_stop(sd_dhcp_client *client)
|
int sd_dhcp_client_stop(sd_dhcp_client *client)
|
||||||
@ -295,14 +364,17 @@ int sd_dhcp_client_stop(sd_dhcp_client *client)
|
|||||||
return client_stop(client, 0);
|
return client_stop(client, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sd_dhcp_client *sd_dhcp_client_new(void)
|
sd_dhcp_client *sd_dhcp_client_new(sd_event *event)
|
||||||
{
|
{
|
||||||
sd_dhcp_client *client;
|
sd_dhcp_client *client;
|
||||||
|
|
||||||
|
assert_return(event, NULL);
|
||||||
|
|
||||||
client = new0(sd_dhcp_client, 1);
|
client = new0(sd_dhcp_client, 1);
|
||||||
if (!client)
|
if (!client)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
client->event = sd_event_ref(event);
|
||||||
client->state = DHCP_STATE_INIT;
|
client->state = DHCP_STATE_INIT;
|
||||||
client->index = -1;
|
client->index = -1;
|
||||||
|
|
||||||
|
@ -34,11 +34,11 @@ static struct ether_addr mac_addr = {
|
|||||||
.ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
|
.ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void test_request_basic(void)
|
static void test_request_basic(sd_event *e)
|
||||||
{
|
{
|
||||||
sd_dhcp_client *client;
|
sd_dhcp_client *client;
|
||||||
|
|
||||||
client = sd_dhcp_client_new();
|
client = sd_dhcp_client_new(e);
|
||||||
|
|
||||||
assert(client);
|
assert(client);
|
||||||
|
|
||||||
@ -172,12 +172,12 @@ int dhcp_network_send_raw_packet(int index, const void *packet, size_t len)
|
|||||||
return 575;
|
return 575;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_discover_message(void)
|
static void test_discover_message(sd_event *e)
|
||||||
{
|
{
|
||||||
sd_dhcp_client *client;
|
sd_dhcp_client *client;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
client = sd_dhcp_client_new();
|
client = sd_dhcp_client_new(e);
|
||||||
assert(client);
|
assert(client);
|
||||||
|
|
||||||
assert(sd_dhcp_client_set_index(client, 42) >= 0);
|
assert(sd_dhcp_client_set_index(client, 42) >= 0);
|
||||||
@ -192,10 +192,15 @@ static void test_discover_message(void)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
test_request_basic();
|
sd_event *e;
|
||||||
|
|
||||||
|
assert(sd_event_new(&e) >= 0);
|
||||||
|
|
||||||
|
test_request_basic(e);
|
||||||
test_checksum();
|
test_checksum();
|
||||||
|
|
||||||
test_discover_message();
|
test_discover_message(e);
|
||||||
|
sd_event_run(e, (uint64_t) -1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <net/ethernet.h>
|
#include <net/ethernet.h>
|
||||||
|
|
||||||
|
#include "sd-event.h"
|
||||||
|
|
||||||
typedef struct sd_dhcp_client sd_dhcp_client;
|
typedef struct sd_dhcp_client sd_dhcp_client;
|
||||||
|
|
||||||
int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option);
|
int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option);
|
||||||
@ -36,6 +38,6 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client,
|
|||||||
|
|
||||||
int sd_dhcp_client_stop(sd_dhcp_client *client);
|
int sd_dhcp_client_stop(sd_dhcp_client *client);
|
||||||
int sd_dhcp_client_start(sd_dhcp_client *client);
|
int sd_dhcp_client_start(sd_dhcp_client *client);
|
||||||
sd_dhcp_client *sd_dhcp_client_new(void);
|
sd_dhcp_client *sd_dhcp_client_new(sd_event *event);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user