]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-dhcp/dhcp-lease.c
sd-dhcp-client: split sd_dhcp_lease from sd_dhcp_client
[thirdparty/systemd.git] / src / libsystemd-dhcp / dhcp-lease.c
1 /***
2 This file is part of systemd.
3
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
5 Copyright (C) 2014 Tom Gundersen
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 <stdlib.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <net/ethernet.h>
26 #include <sys/param.h>
27
28 #include "util.h"
29 #include "list.h"
30
31 #include "dhcp-protocol.h"
32 #include "dhcp-internal.h"
33 #include "dhcp-lease.h"
34 #include "sd-dhcp-client.h"
35
36 int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
37 assert_return(lease, -EINVAL);
38 assert_return(addr, -EINVAL);
39
40 addr->s_addr = lease->address;
41
42 return 0;
43 }
44
45 int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
46 assert_return(lease, -EINVAL);
47 assert_return(mtu, -EINVAL);
48
49 if (lease->mtu)
50 *mtu = lease->mtu;
51 else
52 return -ENOENT;
53
54 return 0;
55 }
56
57 int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, struct in_addr **addr, size_t *addr_size) {
58 assert_return(lease, -EINVAL);
59 assert_return(addr, -EINVAL);
60 assert_return(addr_size, -EINVAL);
61
62 if (lease->dns_size) {
63 *addr_size = lease->dns_size;
64 *addr = lease->dns;
65 } else
66 return -ENOENT;
67
68 return 0;
69 }
70
71 int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
72 assert_return(lease, -EINVAL);
73 assert_return(domainname, -EINVAL);
74
75 if (lease->domainname)
76 *domainname = lease->domainname;
77 else
78 return -ENOENT;
79
80 return 0;
81 }
82
83 int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
84 assert_return(lease, -EINVAL);
85 assert_return(hostname, -EINVAL);
86
87 if (lease->hostname)
88 *hostname = lease->hostname;
89 else
90 return -ENOENT;
91
92 return 0;
93 }
94
95 int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) {
96 assert_return(lease, -EINVAL);
97 assert_return(addr, -EINVAL);
98
99 addr->s_addr = lease->router;
100
101 return 0;
102 }
103
104 int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
105 assert_return(lease, -EINVAL);
106 assert_return(addr, -EINVAL);
107
108 addr->s_addr = lease->subnet_mask;
109
110 return 0;
111 }
112
113 sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) {
114 if (lease)
115 assert_se(REFCNT_INC(lease->n_ref) >= 2);
116
117 return lease;
118 }
119
120 sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
121 if (lease && REFCNT_DEC(lease->n_ref) <= 0) {
122 free(lease->hostname);
123 free(lease->domainname);
124 free(lease->dns);
125 free(lease);
126 }
127
128 return NULL;
129 }
130
131 int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
132 void *user_data) {
133 sd_dhcp_lease *lease = user_data;
134 be32_t val;
135
136 switch(code) {
137
138 case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
139 if (len == 4) {
140 memcpy(&val, option, 4);
141 lease->lifetime = be32toh(val);
142 }
143
144 break;
145
146 case DHCP_OPTION_SERVER_IDENTIFIER:
147 if (len >= 4)
148 memcpy(&lease->server_address, option, 4);
149
150 break;
151
152 case DHCP_OPTION_SUBNET_MASK:
153 if (len >= 4)
154 memcpy(&lease->subnet_mask, option, 4);
155
156 break;
157
158 case DHCP_OPTION_ROUTER:
159 if (len >= 4)
160 memcpy(&lease->router, option, 4);
161
162 break;
163
164 case DHCP_OPTION_DOMAIN_NAME_SERVER:
165 if (len && !(len % 4)) {
166 unsigned i;
167
168 lease->dns_size = len / 4;
169
170 free(lease->dns);
171 lease->dns = new0(struct in_addr, lease->dns_size);
172 if (!lease->dns)
173 return -ENOMEM;
174
175 for (i = 0; i < lease->dns_size; i++) {
176 memcpy(&lease->dns[i].s_addr, option + 4 * i, 4);
177 }
178 }
179
180 break;
181
182 case DHCP_OPTION_INTERFACE_MTU:
183 if (len >= 2) {
184 be16_t mtu;
185
186 memcpy(&mtu, option, 2);
187 lease->mtu = be16toh(mtu);
188
189 if (lease->mtu < 68)
190 lease->mtu = 0;
191 }
192
193 break;
194
195 case DHCP_OPTION_DOMAIN_NAME:
196 if (len >= 1) {
197 free(lease->domainname);
198 lease->domainname = strndup((const char *)option, len);
199 }
200
201 break;
202
203 case DHCP_OPTION_HOST_NAME:
204 if (len >= 1) {
205 free(lease->hostname);
206 lease->hostname = strndup((const char *)option, len);
207 }
208
209 break;
210
211 case DHCP_OPTION_RENEWAL_T1_TIME:
212 if (len == 4) {
213 memcpy(&val, option, 4);
214 lease->t1 = be32toh(val);
215 }
216
217 break;
218
219 case DHCP_OPTION_REBINDING_T2_TIME:
220 if (len == 4) {
221 memcpy(&val, option, 4);
222 lease->t2 = be32toh(val);
223 }
224
225 break;
226 }
227
228 return 0;
229 }
230
231 int dhcp_lease_new(sd_dhcp_lease **ret) {
232 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
233
234 lease = new0(sd_dhcp_lease, 1);
235 if (!lease)
236 return -ENOMEM;
237
238 lease->n_ref = REFCNT_INIT;
239
240 *ret = lease;
241 lease = NULL;
242
243 return 0;
244 }