chiark / gitweb /
78e15892864fa953afdad9e9a2e56d68e1e9ad99
[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->iaaddr.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(preference, -EINVAL);
114
115         if (!lease)
116                 return -EINVAL;
117
118         *preference = lease->preference;
119
120         return 0;
121 }
122
123 int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease) {
124         assert_return(lease, -EINVAL);
125
126         lease->rapid_commit = true;
127
128         return 0;
129 }
130
131 int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit) {
132         assert_return(lease, -EINVAL);
133         assert_return(rapid_commit, -EINVAL);
134
135         *rapid_commit = lease->rapid_commit;
136
137         return 0;
138 }
139
140 int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
141         assert_return(lease, -EINVAL);
142         assert_return(iaid, -EINVAL);
143
144         *iaid = lease->ia.id;
145
146         return 0;
147 }
148
149 int sd_dhcp6_lease_get_next_address(sd_dhcp6_lease *lease,
150                                     struct in6_addr *addr,
151                                     uint32_t *lifetime_preferred,
152                                     uint32_t *lifetime_valid) {
153         assert_return(lease, -EINVAL);
154         assert_return(addr, -EINVAL);
155         assert_return(lifetime_preferred, -EINVAL);
156         assert_return(lifetime_valid, -EINVAL);
157
158         if (!lease->addr_iter)
159                 return -ENOMSG;
160
161         memcpy(addr, &lease->addr_iter->iaaddr.address,
162                 sizeof(struct in6_addr));
163         *lifetime_preferred =
164                 be32toh(lease->addr_iter->iaaddr.lifetime_preferred);
165         *lifetime_valid = be32toh(lease->addr_iter->iaaddr.lifetime_valid);
166
167         lease->addr_iter = lease->addr_iter->addresses_next;
168
169         return 0;
170 }
171
172 int sd_dhcp6_lease_get_first_address(sd_dhcp6_lease *lease,
173                                      struct in6_addr *addr,
174                                      uint32_t *lifetime_preferred,
175                                      uint32_t *lifetime_valid) {
176         assert_return(lease, -EINVAL);
177         assert_return(addr, -EINVAL);
178         assert_return(lifetime_preferred, -EINVAL);
179         assert_return(lifetime_valid, -EINVAL);
180
181         if (!lease->ia.addresses)
182                 return -ENOMSG;
183
184         lease->addr_iter = lease->ia.addresses;
185
186         return sd_dhcp6_lease_get_next_address(lease, addr, lifetime_preferred,
187                                                lifetime_valid);
188 }
189
190 sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
191         if (lease)
192                 assert_se(REFCNT_INC(lease->n_ref) >= 2);
193
194         return lease;
195 }
196
197 sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
198         if (lease && REFCNT_DEC(lease->n_ref) == 0) {
199                 free(lease->serverid);
200                 dhcp6_lease_free_ia(&lease->ia);
201
202                 free(lease);
203         }
204
205         return NULL;
206 }
207
208 int dhcp6_lease_new(sd_dhcp6_lease **ret) {
209         sd_dhcp6_lease *lease;
210
211         lease = new0(sd_dhcp6_lease, 1);
212         if (!lease)
213                 return -ENOMEM;
214
215         lease->n_ref = REFCNT_INIT;
216
217         LIST_HEAD_INIT(lease->ia.addresses);
218
219         *ret = lease;
220         return 0;
221 }