chiark / gitweb /
sd-dhcp6-lease: Add helper function to compute remaining expiry time
[elogind.git] / src / libsystemd-network / sd-dhcp6-lease.c
1 /***
2   This file is part of systemd.
3
4   Copyright (C) 2014 Tom Gundersen
5   Copyright (C) 2014 Intel Corporation. All rights reserved.
6
7   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22
23 #include "util.h"
24
25 #include "dhcp6-lease-internal.h"
26
27 int dhcp6_lease_clear_timers(DHCP6IA *ia) {
28         assert_return(ia, -EINVAL);
29
30         ia->timeout_t1 = sd_event_source_unref(ia->timeout_t1);
31         ia->timeout_t2 = sd_event_source_unref(ia->timeout_t2);
32
33         return 0;
34 }
35
36 int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) {
37         DHCP6Address *addr;
38         uint32_t valid = 0, t;
39
40         assert_return(ia, -EINVAL);
41         assert_return(expire, -EINVAL);
42
43         LIST_FOREACH(addresses, addr, ia->addresses) {
44                 t = be32toh(addr->lifetime_valid);
45                 if (valid < t)
46                         valid = t;
47         }
48
49         t = be32toh(ia->lifetime_t2);
50         if (t > valid)
51                 return -EINVAL;
52
53         *expire = valid - t;
54
55         return 0;
56 }
57
58 DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) {
59         DHCP6Address *address;
60
61         if (!ia)
62                 return NULL;
63
64         dhcp6_lease_clear_timers(ia);
65
66         while (ia->addresses) {
67                 address = ia->addresses;
68
69                 LIST_REMOVE(addresses, ia->addresses, address);
70
71                 free(address);
72         }
73
74         return NULL;
75 }
76
77 int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id,
78                              size_t len) {
79         assert_return(lease, -EINVAL);
80         assert_return(id, -EINVAL);
81
82         free(lease->serverid);
83
84         lease->serverid = memdup(id, len);
85         if (!lease->serverid)
86                 return -EINVAL;
87
88         lease->serverid_len = len;
89
90         return 0;
91 }
92
93 int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len) {
94         assert_return(lease, -EINVAL);
95         assert_return(id, -EINVAL);
96         assert_return(len, -EINVAL);
97
98         *id = lease->serverid;
99         *len = lease->serverid_len;
100
101         return 0;
102 }
103
104 int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference) {
105         assert_return(lease, -EINVAL);
106
107         lease->preference = preference;
108
109         return 0;
110 }
111
112 int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference) {
113         assert_return(lease, -EINVAL);
114         assert_return(preference, -EINVAL);
115
116         *preference = lease->preference;
117
118         return 0;
119 }
120
121 int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
122         assert_return(lease, -EINVAL);
123         assert_return(iaid, -EINVAL);
124
125         *iaid = lease->ia.id;
126
127         return 0;
128 }
129
130 int sd_dhcp6_lease_get_next_address(sd_dhcp6_lease *lease,
131                                     struct in6_addr *addr,
132                                     uint32_t *lifetime_preferred,
133                                     uint32_t *lifetime_valid) {
134         assert_return(lease, -EINVAL);
135         assert_return(addr, -EINVAL);
136         assert_return(lifetime_preferred, -EINVAL);
137         assert_return(lifetime_valid, -EINVAL);
138
139         if (!lease->addr_iter)
140                 return -ENOMSG;
141
142         memcpy(addr, &lease->addr_iter->address, sizeof(struct in6_addr));
143         *lifetime_preferred = be32toh(lease->addr_iter->lifetime_preferred);
144         *lifetime_valid = be32toh(lease->addr_iter->lifetime_valid);
145
146         lease->addr_iter = lease->addr_iter->addresses_next;
147
148         return 0;
149 }
150
151 int sd_dhcp6_lease_get_first_address(sd_dhcp6_lease *lease,
152                                      struct in6_addr *addr,
153                                      uint32_t *lifetime_preferred,
154                                      uint32_t *lifetime_valid) {
155         assert_return(lease, -EINVAL);
156         assert_return(addr, -EINVAL);
157         assert_return(lifetime_preferred, -EINVAL);
158         assert_return(lifetime_valid, -EINVAL);
159
160         if (!lease->ia.addresses)
161                 return -ENOMSG;
162
163         lease->addr_iter = lease->ia.addresses;
164
165         return sd_dhcp6_lease_get_next_address(lease, addr, lifetime_preferred,
166                                                lifetime_valid);
167 }
168
169 sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
170         if (lease)
171                 assert_se(REFCNT_INC(lease->n_ref) >= 2);
172
173         return lease;
174 }
175
176 sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
177         if (lease && REFCNT_DEC(lease->n_ref) <= 0) {
178                 free(lease->serverid);
179                 dhcp6_lease_free_ia(&lease->ia);
180
181                 free(lease);
182         }
183
184         return NULL;
185 }
186
187 int dhcp6_lease_new(sd_dhcp6_lease **ret) {
188         sd_dhcp6_lease *lease;
189
190         lease = new0(sd_dhcp6_lease, 1);
191         if (!lease)
192                 return -ENOMEM;
193
194         lease->n_ref = REFCNT_INIT;
195
196         LIST_HEAD_INIT(lease->ia.addresses);
197
198         *ret = lease;
199         return 0;
200 }