[systemd-devel] [PATCH 22/24] sd-dhcp6-client: Receive and parse a reply and set T1 and T2 timers
Patrik Flykt
patrik.flykt at linux.intel.com
Fri Jun 13 06:45:12 PDT 2014
Receive and parse a Reply from the server. Set up T1 and T2 timers and
notify the library user of an acquired DHCPv6 lease.
---
src/libsystemd-network/dhcp6-protocol.h | 1 +
src/libsystemd-network/sd-dhcp6-client.c | 145 +++++++++++++++++++++++++++++++
src/systemd/sd-dhcp6-client.h | 1 +
3 files changed, 147 insertions(+)
diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h
index a3a8be1..95d37f7 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -70,6 +70,7 @@ enum DHCP6State {
DHCP6_STATE_RS = 1,
DHCP6_STATE_SOLICITATION = 2,
DHCP6_STATE_REQUEST = 3,
+ DHCP6_STATE_BOUND = 4,
};
enum {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 312c84c..15e5ea0 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -239,6 +239,7 @@ static int client_send_message(sd_dhcp6_client *client) {
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_RS:
+ case DHCP6_STATE_BOUND:
return -EINVAL;
}
@@ -258,6 +259,38 @@ static int client_send_message(sd_dhcp6_client *client) {
return 0;
}
+static int client_timeout_t2(sd_event_source *s, uint64_t usec,
+ void *userdata) {
+ sd_dhcp6_client *client = userdata;
+
+ assert_return(s, -EINVAL);
+ assert_return(client, -EINVAL);
+ assert_return(client->lease, -EINVAL);
+
+ client->lease->ia.timeout_t2 =
+ sd_event_source_unref(client->lease->ia.timeout_t2);
+
+ log_dhcp6_client(client, "Timeout T2");
+
+ return 0;
+}
+
+static int client_timeout_t1(sd_event_source *s, uint64_t usec,
+ void *userdata) {
+ sd_dhcp6_client *client = userdata;
+
+ assert_return(s, -EINVAL);
+ assert_return(client, -EINVAL);
+ assert_return(client->lease, -EINVAL);
+
+ client->lease->ia.timeout_t1 =
+ sd_event_source_unref(client->lease->ia.timeout_t1);
+
+ log_dhcp6_client(client, "Timeout T1");
+
+ return 0;
+}
+
static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
void *userdata) {
sd_dhcp6_client *client = userdata;
@@ -316,6 +349,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_RS:
+ case DHCP6_STATE_BOUND:
return 0;
}
@@ -541,6 +575,32 @@ static int client_parse_message(sd_dhcp6_client *client,
return r;
}
+static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,
+ size_t len)
+{
+ int r;
+ _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+
+ if (reply->type != DHCP6_REPLY)
+ return -EINVAL;
+
+ r = dhcp6_lease_new(&lease);
+ if (r < 0)
+ return -ENOMEM;
+
+ r = client_parse_message(client, reply, len, lease);
+ if (r < 0)
+ return r;
+
+ dhcp6_lease_clear_timers(&client->lease->ia);
+
+ client->lease = sd_dhcp6_lease_unref(client->lease);
+ client->lease = lease;
+ lease = NULL;
+
+ return DHCP6_STATE_BOUND;
+}
+
static int client_receive_advertise(sd_dhcp6_client *client,
DHCP6Message *advertise, size_t len) {
int r;
@@ -639,6 +699,29 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
break;
case DHCP6_STATE_REQUEST:
+ r = client_receive_reply(client, message, len);
+ if (r < 0)
+ return 0;
+
+ if (r == DHCP6_STATE_BOUND) {
+
+ r = client_start(client, DHCP6_STATE_BOUND);
+ if (r < 0) {
+ client_stop(client, r);
+ return 0;
+ }
+
+ client = client_notify(client, DHCP6_EVENT_IP_ACQUIRE);
+ if (!client)
+ return 0;
+ }
+
+ break;
+
+ case DHCP6_STATE_BOUND:
+
+ break;
+
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_RS:
return 0;
@@ -655,6 +738,8 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
{
int r;
+ usec_t timeout, time_now;
+ char time_string[FORMAT_TIMESPAN_MAX];
assert_return(client, -EINVAL);
assert_return(client->event, -EINVAL);
@@ -698,9 +783,69 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
break;
case DHCP6_STATE_REQUEST:
+
client->state = state;
break;
+
+ case DHCP6_STATE_BOUND:
+
+ r = sd_event_now(client->event, CLOCK_MONOTONIC, &time_now);
+ if (r < 0)
+ return r;
+
+ if (client->lease->ia.lifetime_t1 == 0xffffffff ||
+ client->lease->ia.lifetime_t2 == 0xffffffff) {
+
+ log_dhcp6_client(client, "infinite T1 0x%08x or T2 "
+ "0x%08x",
+ be32toh(client->lease->ia.lifetime_t1),
+ be32toh(client->lease->ia.lifetime_t2));
+
+ return 0;
+ }
+
+ timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t1) * USEC_PER_SEC);
+
+ log_dhcp6_client(client, "T1 expires in %s",
+ format_timespan(time_string,
+ FORMAT_TIMESPAN_MAX,
+ timeout, 0));
+
+ r = sd_event_add_time(client->event,
+ &client->lease->ia.timeout_t1,
+ CLOCK_MONOTONIC, time_now + timeout,
+ 10 * USEC_PER_SEC, client_timeout_t1,
+ client);
+ if (r < 0)
+ return r;
+
+ r = sd_event_source_set_priority(client->lease->ia.timeout_t1,
+ client->event_priority);
+ if (r < 0)
+ return r;
+
+ timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t2) * USEC_PER_SEC);
+
+ log_dhcp6_client(client, "T2 expires in %s",
+ format_timespan(time_string,
+ FORMAT_TIMESPAN_MAX,
+ timeout, 0));
+
+ r = sd_event_add_time(client->event,
+ &client->lease->ia.timeout_t2,
+ CLOCK_MONOTONIC, time_now + timeout,
+ 10 * USEC_PER_SEC, client_timeout_t2,
+ client);
+ if (r < 0)
+ return r;
+
+ r = sd_event_source_set_priority(client->lease->ia.timeout_t2,
+ client->event_priority);
+ if (r < 0)
+ return r;
+
+ return 0;
}
client->transaction_id = random_u32() & htobe32(0x00ffffff);
diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
index aadb622..81e26fe 100644
--- a/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/sd-dhcp6-client.h
@@ -33,6 +33,7 @@ enum {
DHCP6_EVENT_NO_STATEFUL_CONFIGURATION = 10,
DHCP6_EVENT_RESEND_EXPIRE = 11,
DHCP6_EVENT_RETRANS_MAX = 12,
+ DHCP6_EVENT_IP_ACQUIRE = 13,
};
typedef struct sd_dhcp6_client sd_dhcp6_client;
--
1.9.1
More information about the systemd-devel
mailing list