mirror of
https://github.com/systemd/systemd.git
synced 2024-11-01 17:51:22 +03:00
sd-dhcp6-client: Implement Information Request message
Implement Information Request message according to RFC 3315, section 18.1.5. with the excepion that the first message is not delayed by a random amount. Instead systemd-networkd is supposed to take care of desynchronizing between other clients. Initialize the DHCPv6 client structure in sd_dhcp6_client_start() as this allows toggling between information request and normal DHCPv6 address aquisition modes.
This commit is contained in:
parent
fab15fec24
commit
bbfa43ca37
@ -51,6 +51,8 @@ enum {
|
||||
DHCP6_PORT_CLIENT = 546,
|
||||
};
|
||||
|
||||
#define DHCP6_INF_TIMEOUT 1 * USEC_PER_SEC
|
||||
#define DHCP6_INF_MAX_RT 120 * USEC_PER_SEC
|
||||
#define DHCP6_SOL_MAX_DELAY 1 * USEC_PER_SEC
|
||||
#define DHCP6_SOL_TIMEOUT 1 * USEC_PER_SEC
|
||||
#define DHCP6_SOL_MAX_RT 120 * USEC_PER_SEC
|
||||
@ -71,6 +73,7 @@ enum {
|
||||
|
||||
enum DHCP6State {
|
||||
DHCP6_STATE_STOPPED = 0,
|
||||
DHCP6_STATE_INFORMATION_REQUEST = 1,
|
||||
DHCP6_STATE_SOLICITATION = 2,
|
||||
DHCP6_STATE_REQUEST = 3,
|
||||
DHCP6_STATE_BOUND = 4,
|
||||
|
@ -62,6 +62,7 @@ struct sd_dhcp6_client {
|
||||
usec_t transaction_start;
|
||||
struct sd_dhcp6_lease *lease;
|
||||
int fd;
|
||||
bool information_request;
|
||||
be16_t *req_opts;
|
||||
size_t req_opts_allocated;
|
||||
size_t req_opts_len;
|
||||
@ -227,6 +228,25 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *du
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client,
|
||||
bool enabled) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
client->information_request = enabled;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client,
|
||||
bool *enabled) {
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(enabled, -EINVAL);
|
||||
|
||||
*enabled = client->information_request;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
|
||||
uint16_t option) {
|
||||
size_t t;
|
||||
@ -333,6 +353,11 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
||||
message->transaction_id = client->transaction_id;
|
||||
|
||||
switch(client->state) {
|
||||
case DHCP6_STATE_INFORMATION_REQUEST:
|
||||
message->type = DHCP6_INFORMATION_REQUEST;
|
||||
|
||||
break;
|
||||
|
||||
case DHCP6_STATE_SOLICITATION:
|
||||
message->type = DHCP6_SOLICIT;
|
||||
|
||||
@ -494,6 +519,12 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
|
||||
client->timeout_resend = sd_event_source_unref(client->timeout_resend);
|
||||
|
||||
switch (client->state) {
|
||||
case DHCP6_STATE_INFORMATION_REQUEST:
|
||||
init_retransmit_time = DHCP6_INF_TIMEOUT;
|
||||
max_retransmit_time = DHCP6_INF_MAX_RT;
|
||||
|
||||
break;
|
||||
|
||||
case DHCP6_STATE_SOLICITATION:
|
||||
|
||||
if (client->retransmit_count && client->lease) {
|
||||
@ -744,6 +775,12 @@ static int client_parse_message(sd_dhcp6_client *client,
|
||||
break;
|
||||
|
||||
case DHCP6_OPTION_IA_NA:
|
||||
if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
|
||||
log_dhcp6_client(client, "Information request ignoring IA NA option");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
r = dhcp6_option_parse_ia(&optval, &optlen, optcode,
|
||||
&lease->ia);
|
||||
if (r < 0 && r != -ENOMSG)
|
||||
@ -779,10 +816,12 @@ static int client_parse_message(sd_dhcp6_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = dhcp6_lease_get_serverid(lease, &id, &id_len);
|
||||
if (r < 0)
|
||||
log_dhcp6_client(client, "%s has no server id",
|
||||
dhcp6_message_type_to_string(message->type));
|
||||
if (client->state != DHCP6_STATE_INFORMATION_REQUEST) {
|
||||
r = dhcp6_lease_get_serverid(lease, &id, &id_len);
|
||||
if (r < 0)
|
||||
log_dhcp6_client(client, "%s has no server id",
|
||||
dhcp6_message_type_to_string(message->type));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -814,12 +853,15 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (client->lease)
|
||||
if (client->lease) {
|
||||
dhcp6_lease_clear_timers(&client->lease->ia);
|
||||
client->lease = sd_dhcp6_lease_unref(client->lease);
|
||||
}
|
||||
|
||||
client->lease = sd_dhcp6_lease_unref(client->lease);
|
||||
client->lease = lease;
|
||||
lease = NULL;
|
||||
if (client->state != DHCP6_STATE_INFORMATION_REQUEST) {
|
||||
client->lease = lease;
|
||||
lease = NULL;
|
||||
}
|
||||
|
||||
return DHCP6_STATE_BOUND;
|
||||
}
|
||||
@ -846,7 +888,8 @@ static int client_receive_advertise(sd_dhcp6_client *client,
|
||||
return r;
|
||||
|
||||
r = dhcp6_lease_get_preference(client->lease, &pref_lease);
|
||||
if (!client->lease || r < 0 || pref_advertise > pref_lease) {
|
||||
|
||||
if (r < 0 || pref_advertise > pref_lease) {
|
||||
sd_dhcp6_lease_unref(client->lease);
|
||||
client->lease = lease;
|
||||
lease = NULL;
|
||||
@ -913,6 +956,17 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
|
||||
return 0;
|
||||
|
||||
switch (client->state) {
|
||||
case DHCP6_STATE_INFORMATION_REQUEST:
|
||||
r = client_receive_reply(client, message, len);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
client_notify(client, DHCP6_EVENT_INFORMATION_REQUEST);
|
||||
|
||||
client_start(client, DHCP6_STATE_STOPPED);
|
||||
|
||||
break;
|
||||
|
||||
case DHCP6_STATE_SOLICITATION:
|
||||
r = client_receive_advertise(client, message, len);
|
||||
|
||||
@ -988,37 +1042,19 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
|
||||
|
||||
switch (state) {
|
||||
case DHCP6_STATE_STOPPED:
|
||||
if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
|
||||
client->state = DHCP6_STATE_STOPPED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fall through */
|
||||
case DHCP6_STATE_SOLICITATION:
|
||||
|
||||
r = client_ensure_iaid(client);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp6_network_bind_udp_socket(client->index, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
client->fd = r;
|
||||
|
||||
r = sd_event_add_io(client->event, &client->receive_message,
|
||||
client->fd, EPOLLIN, client_receive_message,
|
||||
client);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_source_set_priority(client->receive_message,
|
||||
client->event_priority);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_source_set_description(client->receive_message, "dhcp6-receive-message");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
client->state = DHCP6_STATE_SOLICITATION;
|
||||
|
||||
break;
|
||||
|
||||
case DHCP6_STATE_INFORMATION_REQUEST:
|
||||
case DHCP6_STATE_REQUEST:
|
||||
case DHCP6_STATE_RENEW:
|
||||
case DHCP6_STATE_REBIND:
|
||||
@ -1123,6 +1159,7 @@ int sd_dhcp6_client_stop(sd_dhcp6_client *client)
|
||||
int sd_dhcp6_client_start(sd_dhcp6_client *client)
|
||||
{
|
||||
int r = 0;
|
||||
enum DHCP6State state = DHCP6_STATE_SOLICITATION;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(client->event, -EINVAL);
|
||||
@ -1132,7 +1169,44 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client)
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return client_start(client, DHCP6_STATE_SOLICITATION);
|
||||
r = client_ensure_iaid(client);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp6_network_bind_udp_socket(client->index, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
client->fd = r;
|
||||
|
||||
r = sd_event_add_io(client->event, &client->receive_message,
|
||||
client->fd, EPOLLIN, client_receive_message,
|
||||
client);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_event_source_set_priority(client->receive_message,
|
||||
client->event_priority);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_event_source_set_description(client->receive_message,
|
||||
"dhcp6-receive-message");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
if (client->information_request)
|
||||
state = DHCP6_STATE_INFORMATION_REQUEST;
|
||||
|
||||
log_dhcp6_client(client, "Started in %s mode",
|
||||
client->information_request? "Information request":
|
||||
"Managed");
|
||||
|
||||
return client_start(client, state);
|
||||
|
||||
error:
|
||||
client_reset(client);
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
|
||||
|
@ -33,6 +33,7 @@ enum {
|
||||
DHCP6_EVENT_RESEND_EXPIRE = 10,
|
||||
DHCP6_EVENT_RETRANS_MAX = 11,
|
||||
DHCP6_EVENT_IP_ACQUIRE = 12,
|
||||
DHCP6_EVENT_INFORMATION_REQUEST = 13,
|
||||
};
|
||||
|
||||
typedef struct sd_dhcp6_client sd_dhcp6_client;
|
||||
@ -47,6 +48,10 @@ int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
|
||||
size_t addr_len, uint16_t arp_type);
|
||||
int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid,
|
||||
size_t duid_len);
|
||||
int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client,
|
||||
bool enabled);
|
||||
int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client,
|
||||
bool *enabled);
|
||||
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
|
||||
uint16_t option);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user