config: set RFC defaults for preferred lifetime
[project/odhcpd.git] / src / dhcpv4.c
1 /**
2 * Copyright (C) 2012-2013 Steven Barth <steven@midlink.org>
3 * Copyright (C) 2016 Hans Dedecker <dedeckeh@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License v2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 *
15 */
16
17 #include <time.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <stddef.h>
22 #include <stdlib.h>
23 #include <resolv.h>
24 #include <limits.h>
25 #include <net/if.h>
26 #include <net/if_arp.h>
27 #include <netinet/ip.h>
28 #include <sys/ioctl.h>
29 #include <sys/timerfd.h>
30 #include <arpa/inet.h>
31
32 #include <libubox/md5.h>
33
34 #include "odhcpd.h"
35 #include "dhcpv4.h"
36 #include "dhcpv6.h"
37
38 #define PACKET_SIZE(start, end) (((uint8_t *)end - (uint8_t *)start) < DHCPV4_MIN_PACKET_SIZE ? \
39 DHCPV4_MIN_PACKET_SIZE : (uint8_t *)end - (uint8_t *)start)
40 #define MAX_PREFIX_LEN 28
41
42 static void dhcpv4_netevent_cb(unsigned long event, struct netevent_handler_info *info);
43 static int setup_dhcpv4_addresses(struct interface *iface);
44 static bool addr_is_fr_ip(struct interface *iface, struct in_addr *addr);
45 static void valid_until_cb(struct uloop_timeout *event);
46 static void handle_addrlist_change(struct interface *iface);
47 static void dhcpv4_fr_start(struct dhcp_assignment *a);
48 static void dhcpv4_fr_rand_delay(struct dhcp_assignment *a);
49 static void dhcpv4_fr_stop(struct dhcp_assignment *a);
50 static void handle_dhcpv4(void *addr, void *data, size_t len,
51 struct interface *iface, void *dest_addr);
52 static struct dhcp_assignment* dhcpv4_lease(struct interface *iface,
53 enum dhcpv4_msg msg, const uint8_t *mac, const uint32_t reqaddr,
54 uint32_t *leasetime, const char *hostname, const size_t hostname_len,
55 const bool accept_fr_nonce, bool *incl_fr_opt, uint32_t *fr_serverid,
56 const char *reqopts, const size_t reqopts_len);
57
58 static struct netevent_handler dhcpv4_netevent_handler = { .cb = dhcpv4_netevent_cb, };
59 static struct uloop_timeout valid_until_timeout = {.cb = valid_until_cb};
60 static uint32_t serial = 0;
61
62 struct odhcpd_ref_ip {
63 struct list_head head;
64 int ref_cnt;
65 struct odhcpd_ipaddr addr;
66 };
67
68 /* Create socket and register events */
69 int dhcpv4_init(void)
70 {
71 uloop_timeout_set(&valid_until_timeout, 1000);
72 netlink_add_netevent_handler(&dhcpv4_netevent_handler);
73
74 return 0;
75 }
76
77 int dhcpv4_setup_interface(struct interface *iface, bool enable)
78 {
79 int ret = 0;
80
81 enable = enable && (iface->dhcpv4 != MODE_DISABLED);
82
83 if (iface->dhcpv4_event.uloop.fd >= 0) {
84 uloop_fd_delete(&iface->dhcpv4_event.uloop);
85 close(iface->dhcpv4_event.uloop.fd);
86 iface->dhcpv4_event.uloop.fd = -1;
87 }
88
89 if (enable) {
90 struct sockaddr_in bind_addr = {AF_INET, htons(DHCPV4_SERVER_PORT),
91 {INADDR_ANY}, {0}};
92 int val = 1;
93
94 iface->dhcpv4_event.uloop.fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
95 if (iface->dhcpv4_event.uloop.fd < 0) {
96 syslog(LOG_ERR, "socket(AF_INET): %m");
97 ret = -1;
98 goto out;
99 }
100
101 /* Basic IPv4 configuration */
102 if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_REUSEADDR,
103 &val, sizeof(val)) < 0) {
104 syslog(LOG_ERR, "setsockopt(SO_REUSEADDR): %m");
105 ret = -1;
106 goto out;
107 }
108
109 if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BROADCAST,
110 &val, sizeof(val)) < 0) {
111 syslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m");
112 ret = -1;
113 goto out;
114 }
115
116 if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_PKTINFO,
117 &val, sizeof(val)) < 0) {
118 syslog(LOG_ERR, "setsockopt(IP_PKTINFO): %m");
119 ret = -1;
120 goto out;
121 }
122
123 val = IPTOS_PREC_INTERNETCONTROL;
124 if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_TOS,
125 &val, sizeof(val)) < 0) {
126 syslog(LOG_ERR, "setsockopt(IP_TOS): %m");
127 ret = -1;
128 goto out;
129 }
130
131 val = IP_PMTUDISC_DONT;
132 if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_MTU_DISCOVER,
133 &val, sizeof(val)) < 0) {
134 syslog(LOG_ERR, "setsockopt(IP_MTU_DISCOVER): %m");
135 ret = -1;
136 goto out;
137 }
138
139 if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BINDTODEVICE,
140 iface->ifname, strlen(iface->ifname)) < 0) {
141 syslog(LOG_ERR, "setsockopt(SO_BINDTODEVICE): %m");
142 ret = -1;
143 goto out;
144 }
145
146 if (bind(iface->dhcpv4_event.uloop.fd, (struct sockaddr*)&bind_addr,
147 sizeof(bind_addr)) < 0) {
148 syslog(LOG_ERR, "bind(): %m");
149 ret = -1;
150 goto out;
151 }
152
153 if (setup_dhcpv4_addresses(iface) < 0) {
154 ret = -1;
155 goto out;
156 }
157
158 iface->dhcpv4_event.handle_dgram = handle_dhcpv4;
159 odhcpd_register(&iface->dhcpv4_event);
160 } else {
161 while (!list_empty(&iface->dhcpv4_assignments))
162 free_assignment(list_first_entry(&iface->dhcpv4_assignments,
163 struct dhcp_assignment, head));
164 }
165
166 out:
167 if (ret < 0 && iface->dhcpv4_event.uloop.fd >= 0) {
168 close(iface->dhcpv4_event.uloop.fd);
169 iface->dhcpv4_event.uloop.fd = -1;
170 }
171
172 return ret;
173 }
174
175
176 static void dhcpv4_netevent_cb(unsigned long event, struct netevent_handler_info *info)
177 {
178 struct interface *iface = info->iface;
179
180 if (!iface || iface->dhcpv4 == MODE_DISABLED)
181 return;
182
183 switch (event) {
184 case NETEV_IFINDEX_CHANGE:
185 dhcpv4_setup_interface(iface, true);
186 break;
187 case NETEV_ADDRLIST_CHANGE:
188 handle_addrlist_change(iface);
189 break;
190 default:
191 break;
192 }
193 }
194
195 static struct dhcp_assignment *find_assignment_by_hwaddr(struct interface *iface, const uint8_t *hwaddr)
196 {
197 struct dhcp_assignment *a;
198
199 list_for_each_entry(a, &iface->dhcpv4_assignments, head)
200 if (!memcmp(a->hwaddr, hwaddr, 6))
201 return a;
202
203 return NULL;
204 }
205
206 static int setup_dhcpv4_addresses(struct interface *iface)
207 {
208 iface->dhcpv4_start_ip.s_addr = INADDR_ANY;
209 iface->dhcpv4_end_ip.s_addr = INADDR_ANY;
210 iface->dhcpv4_local.s_addr = INADDR_ANY;
211 iface->dhcpv4_bcast.s_addr = INADDR_ANY;
212 iface->dhcpv4_mask.s_addr = INADDR_ANY;
213
214 /* Sanity checks */
215 if (iface->dhcpv4_start.s_addr & htonl(0xffff0000) ||
216 iface->dhcpv4_end.s_addr & htonl(0xffff0000) ||
217 ntohl(iface->dhcpv4_start.s_addr) > ntohl(iface->dhcpv4_end.s_addr)) {
218 syslog(LOG_WARNING, "Invalid DHCP range for %s", iface->name);
219 return -1;
220 }
221
222 if (!iface->addr4_len) {
223 syslog(LOG_WARNING, "No network(s) available on %s", iface->name);
224 return -1;
225 }
226
227 uint32_t start = ntohl(iface->dhcpv4_start.s_addr);
228 uint32_t end = ntohl(iface->dhcpv4_end.s_addr);
229
230 for (size_t i = 0; i < iface->addr4_len && start && end; i++) {
231 struct in_addr *addr = &iface->addr4[i].addr.in;
232 struct in_addr mask;
233
234 if (addr_is_fr_ip(iface, addr))
235 continue;
236
237 odhcpd_bitlen2netmask(false, iface->addr4[i].prefix, &mask);
238 if ((start & ntohl(~mask.s_addr)) == start &&
239 (end & ntohl(~mask.s_addr)) == end &&
240 end < ntohl(~mask.s_addr)) { /* Exclude broadcast address */
241 iface->dhcpv4_start_ip.s_addr = htonl(start) |
242 (addr->s_addr & mask.s_addr);
243 iface->dhcpv4_end_ip.s_addr = htonl(end) |
244 (addr->s_addr & mask.s_addr);
245 iface->dhcpv4_local = *addr;
246 iface->dhcpv4_bcast = iface->addr4[i].broadcast;
247 iface->dhcpv4_mask = mask;
248 return 0;
249 }
250 }
251
252 /* Don't allocate IP range for subnets smaller than /28 */
253 if (iface->addr4[0].prefix > MAX_PREFIX_LEN) {
254 syslog(LOG_WARNING, "Auto allocation of DHCP range fails on %s (prefix length must be < %d).", iface->name, MAX_PREFIX_LEN + 1);
255 return -1;
256 }
257
258 iface->dhcpv4_local = iface->addr4[0].addr.in;
259 iface->dhcpv4_bcast = iface->addr4[0].broadcast;
260 odhcpd_bitlen2netmask(false, iface->addr4[0].prefix, &iface->dhcpv4_mask);
261 end = start = iface->dhcpv4_local.s_addr & iface->dhcpv4_mask.s_addr;
262
263 /* Auto allocate ranges */
264 if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffff00) { /* /24, 150 of 256, [100..249] */
265 iface->dhcpv4_start_ip.s_addr = start | htonl(100);
266 iface->dhcpv4_end_ip.s_addr = end | htonl(100 + 150 - 1);
267 } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffff80) { /* /25, 100 of 128, [20..119] */
268 iface->dhcpv4_start_ip.s_addr = start | htonl(20);
269 iface->dhcpv4_end_ip.s_addr = end | htonl(20 + 100 - 1);
270 } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffffc0) { /* /26, 50 of 64, [10..59] */
271 iface->dhcpv4_start_ip.s_addr = start | htonl(10);
272 iface->dhcpv4_end_ip.s_addr = end | htonl(10 + 50 - 1);
273 } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffffe0) { /* /27, 20 of 32, [10..29] */
274 iface->dhcpv4_start_ip.s_addr = start | htonl(10);
275 iface->dhcpv4_end_ip.s_addr = end | htonl(10 + 20 - 1);
276 } else { /* /28, 10 of 16, [3..12] */
277 iface->dhcpv4_start_ip.s_addr = start | htonl(3);
278 iface->dhcpv4_end_ip.s_addr = end | htonl(3 + 10 - 1);
279 }
280
281 return 0;
282 }
283
284 static void inc_ref_cnt_ip(struct odhcpd_ref_ip **ptr, struct odhcpd_ref_ip *ip)
285 {
286 *ptr = ip;
287 ip->ref_cnt++;
288 }
289
290 static void decr_ref_cnt_ip(struct odhcpd_ref_ip **ptr, struct interface *iface)
291 {
292 struct odhcpd_ref_ip *ip = *ptr;
293
294 if (--ip->ref_cnt == 0) {
295 netlink_setup_addr(&ip->addr, iface->ifindex, false, false);
296
297 list_del(&ip->head);
298 free(ip);
299 }
300
301 *ptr = NULL;
302 }
303
304 static bool addr_is_fr_ip(struct interface *iface, struct in_addr *addr)
305 {
306 struct odhcpd_ref_ip *p;
307
308 list_for_each_entry(p, &iface->dhcpv4_fr_ips, head) {
309 if (addr->s_addr == p->addr.addr.in.s_addr)
310 return true;
311 }
312
313 return false;
314 }
315
316 static bool leases_require_fr(struct interface *iface, struct odhcpd_ipaddr *addr,
317 uint32_t mask)
318 {
319 struct dhcp_assignment *a = NULL;
320 struct odhcpd_ref_ip *fr_ip = NULL;
321
322 list_for_each_entry(a, &iface->dhcpv4_assignments, head) {
323 if ((a->accept_fr_nonce || iface->dhcpv4_forcereconf) &&
324 !a->fr_ip &&
325 ((a->addr & mask) == (addr->addr.in.s_addr & mask))) {
326 if (!fr_ip) {
327 fr_ip = calloc(1, sizeof(*fr_ip));
328 if (!fr_ip)
329 break;
330
331 list_add(&fr_ip->head, &iface->dhcpv4_fr_ips);
332 fr_ip->addr = *addr;
333 }
334 inc_ref_cnt_ip(&a->fr_ip, fr_ip);
335 }
336 }
337
338 return fr_ip ? true : false;
339 }
340
341 static void valid_until_cb(struct uloop_timeout *event)
342 {
343 struct interface *iface;
344 time_t now = odhcpd_time();
345
346 avl_for_each_element(&interfaces, iface, avl) {
347 struct dhcp_assignment *a, *n;
348
349 if (iface->dhcpv4 != MODE_SERVER)
350 continue;
351
352 list_for_each_entry_safe(a, n, &iface->dhcpv4_assignments, head) {
353 if (!INFINITE_VALID(a->valid_until) && a->valid_until < now)
354 free_assignment(a);
355 }
356 }
357 uloop_timeout_set(event, 1000);
358 }
359
360 static void handle_addrlist_change(struct interface *iface)
361 {
362 struct odhcpd_ipaddr ip;
363 struct odhcpd_ref_ip *a;
364 struct dhcp_assignment *c;
365 uint32_t mask = iface->dhcpv4_mask.s_addr;
366
367 memset(&ip, 0, sizeof(ip));
368 ip.addr.in = iface->dhcpv4_local;
369 ip.prefix = odhcpd_netmask2bitlen(false, &iface->dhcpv4_mask);
370 ip.broadcast = iface->dhcpv4_bcast;
371
372 setup_dhcpv4_addresses(iface);
373
374 if ((ip.addr.in.s_addr & mask) ==
375 (iface->dhcpv4_local.s_addr & iface->dhcpv4_mask.s_addr))
376 return;
377
378 if (ip.addr.in.s_addr && !leases_require_fr(iface, &ip, mask))
379 return;
380
381 if (iface->dhcpv4_local.s_addr == INADDR_ANY || list_empty(&iface->dhcpv4_fr_ips))
382 return;
383
384 a = list_first_entry(&iface->dhcpv4_fr_ips, struct odhcpd_ref_ip, head);
385
386 if (netlink_setup_addr(&a->addr, iface->ifindex, false, true)) {
387 syslog(LOG_WARNING, "Failed to add ip address on %s", iface->name);
388 return;
389 }
390
391 list_for_each_entry(c, &iface->dhcpv4_assignments, head) {
392 if ((c->flags & OAF_BOUND) && c->fr_ip && !c->fr_cnt) {
393 if (c->accept_fr_nonce || iface->dhcpv4_forcereconf)
394 dhcpv4_fr_rand_delay(c);
395 else
396 dhcpv4_fr_stop(c);
397 }
398 }
399 }
400
401 static char *dhcpv4_msg_to_string(uint8_t reqmsg)
402 {
403 switch (reqmsg) {
404 case (DHCPV4_MSG_DISCOVER):
405 return "DHCPV4_MSG_DISCOVER";
406 case (DHCPV4_MSG_OFFER):
407 return "DHCPV4_MSG_OFFER";
408 case (DHCPV4_MSG_REQUEST):
409 return "DHCPV4_MSG_REQUEST";
410 case (DHCPV4_MSG_DECLINE):
411 return "DHCPV4_MSG_DECLINE";
412 case (DHCPV4_MSG_ACK):
413 return "DHCPV4_MSG_ACK";
414 case (DHCPV4_MSG_NAK):
415 return "DHCPV4_MSG_NAK";
416 case (DHCPV4_MSG_RELEASE):
417 return "DHCPV4_MSG_RELEASE";
418 case (DHCPV4_MSG_INFORM):
419 return "DHCPV4_MSG_INFORM";
420 case (DHCPV4_MSG_FORCERENEW):
421 return "DHCPV4_MSG_FORCERENEW";
422 default:
423 return "UNKNOWN";
424 }
425 }
426
427 static void dhcpv4_free_assignment(struct dhcp_assignment *a)
428 {
429 if (a->fr_ip)
430 dhcpv4_fr_stop(a);
431 }
432
433 static void dhcpv4_put(struct dhcpv4_message *msg, uint8_t **cookie,
434 uint8_t type, uint8_t len, const void *data)
435 {
436 uint8_t *c = *cookie;
437 uint8_t *end = (uint8_t *)msg + sizeof(*msg);
438 bool tag_only = type == DHCPV4_OPT_PAD || type == DHCPV4_OPT_END;
439 int total_len = tag_only ? 1 : 2 + len;
440
441 if (*cookie + total_len > end)
442 return;
443
444 *cookie += total_len;
445 *c++ = type;
446
447 if (tag_only)
448 return;
449
450 *c++ = len;
451 memcpy(c, data, len);
452 }
453
454 static void dhcpv4_fr_send(struct dhcp_assignment *a)
455 {
456 struct dhcpv4_message fr_msg = {
457 .op = DHCPV4_BOOTREPLY,
458 .htype = 1,
459 .hlen = 6,
460 .hops = 0,
461 .secs = 0,
462 .flags = 0,
463 .ciaddr = {INADDR_ANY},
464 .yiaddr = {INADDR_ANY},
465 .siaddr = {INADDR_ANY},
466 .giaddr = {INADDR_ANY},
467 .chaddr = {0},
468 .sname = {0},
469 .file = {0},
470 };
471 struct dhcpv4_auth_forcerenew *auth_o, auth = {
472 .protocol = 3,
473 .algorithm = 1,
474 .rdm = 0,
475 .replay = {htonl(time(NULL)), htonl(++serial)},
476 .type = 2,
477 .key = {0},
478 };
479 struct interface *iface = a->iface;
480
481 odhcpd_urandom(&fr_msg.xid, sizeof(fr_msg.xid));
482 memcpy(fr_msg.chaddr, a->hwaddr, fr_msg.hlen);
483
484 fr_msg.options[0] = 0x63;
485 fr_msg.options[1] = 0x82;
486 fr_msg.options[2] = 0x53;
487 fr_msg.options[3] = 0x63;
488
489 uint8_t *cookie = &fr_msg.options[4];
490 uint8_t msg = DHCPV4_MSG_FORCERENEW;
491
492 dhcpv4_put(&fr_msg, &cookie, DHCPV4_OPT_MESSAGE, 1, &msg);
493 if (a->accept_fr_nonce) {
494 dhcpv4_put(&fr_msg, &cookie, DHCPV4_OPT_AUTHENTICATION, sizeof(auth), &auth);
495 auth_o = (struct dhcpv4_auth_forcerenew *)(cookie - sizeof(auth));
496 dhcpv4_put(&fr_msg, &cookie, DHCPV4_OPT_END, 0, NULL);
497
498 md5_ctx_t md5;
499 uint8_t secretbytes[64];
500 memset(secretbytes, 0, sizeof(secretbytes));
501 memcpy(secretbytes, a->key, sizeof(a->key));
502
503 for (size_t i = 0; i < sizeof(secretbytes); ++i)
504 secretbytes[i] ^= 0x36;
505
506 md5_begin(&md5);
507 md5_hash(secretbytes, sizeof(secretbytes), &md5);
508 md5_hash(&fr_msg, sizeof(fr_msg), &md5);
509 md5_end(auth_o->key, &md5);
510
511 for (size_t i = 0; i < sizeof(secretbytes); ++i) {
512 secretbytes[i] ^= 0x36;
513 secretbytes[i] ^= 0x5c;
514 }
515
516 md5_begin(&md5);
517 md5_hash(secretbytes, sizeof(secretbytes), &md5);
518 md5_hash(auth_o->key, sizeof(auth_o->key), &md5);
519 md5_end(auth_o->key, &md5);
520 } else {
521 dhcpv4_put(&fr_msg, &cookie, DHCPV4_OPT_SERVERID, 4,
522 &a->fr_ip->addr.addr.in.s_addr);
523 dhcpv4_put(&fr_msg, &cookie, DHCPV4_OPT_END, 0, NULL);
524 }
525
526 struct sockaddr_in dest;
527 memset(&dest, 0, sizeof(dest));
528 dest.sin_family = AF_INET;
529 dest.sin_port = htons(DHCPV4_CLIENT_PORT);
530 dest.sin_addr.s_addr = a->addr;
531
532 if (sendto(iface->dhcpv4_event.uloop.fd, &fr_msg, PACKET_SIZE(&fr_msg, cookie),
533 MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0)
534 syslog(LOG_ERR, "Failed to send %s to %s - %s: %m", dhcpv4_msg_to_string(msg),
535 odhcpd_print_mac(a->hwaddr, sizeof(a->hwaddr)), inet_ntoa(dest.sin_addr));
536 else
537 syslog(LOG_DEBUG, "Sent %s to %s - %s", dhcpv4_msg_to_string(msg),
538 odhcpd_print_mac(a->hwaddr, sizeof(a->hwaddr)), inet_ntoa(dest.sin_addr));
539 }
540
541 static void dhcpv4_fr_timer(struct uloop_timeout *event)
542 {
543 struct dhcp_assignment *a = container_of(event, struct dhcp_assignment, fr_timer);
544
545 if (a->fr_cnt > 0 && a->fr_cnt < 8) {
546 dhcpv4_fr_send(a);
547 uloop_timeout_set(&a->fr_timer, 1000 << a->fr_cnt);
548 a->fr_cnt++;
549 } else
550 dhcpv4_fr_stop(a);
551 }
552
553 static void dhcpv4_fr_start(struct dhcp_assignment *a)
554 {
555 uloop_timeout_set(&a->fr_timer, 1000 << a->fr_cnt);
556 a->fr_timer.cb = dhcpv4_fr_timer;
557 a->fr_cnt++;
558
559 dhcpv4_fr_send(a);
560 }
561
562 static void dhcpv4_fr_delay_timer(struct uloop_timeout *event)
563 {
564 struct dhcp_assignment *a = container_of(event, struct dhcp_assignment, fr_timer);
565 struct interface *iface = a->iface;
566
567 (iface->dhcpv4_event.uloop.fd == -1 ? dhcpv4_fr_rand_delay(a) : dhcpv4_fr_start(a));
568 }
569
570 static void dhcpv4_fr_rand_delay(struct dhcp_assignment *a)
571 {
572 #define MIN_DELAY 500
573 #define MAX_FUZZ 500
574 int msecs;
575
576 odhcpd_urandom(&msecs, sizeof(msecs));
577
578 msecs = labs(msecs)%MAX_FUZZ + MIN_DELAY;
579
580 uloop_timeout_set(&a->fr_timer, msecs);
581 a->fr_timer.cb = dhcpv4_fr_delay_timer;
582 }
583
584 static void dhcpv4_fr_stop(struct dhcp_assignment *a)
585 {
586 uloop_timeout_cancel(&a->fr_timer);
587 decr_ref_cnt_ip(&a->fr_ip, a->iface);
588 a->fr_cnt = 0;
589 a->fr_timer.cb = NULL;
590 }
591
592 static int dhcpv4_send_reply(const void *buf, size_t len,
593 const struct sockaddr *dest, socklen_t dest_len,
594 void *opaque)
595 {
596 int *sock = opaque;
597
598 return sendto(*sock, buf, len, MSG_DONTWAIT, dest, dest_len);
599 }
600
601 /* Handler for DHCPv4 messages */
602 static void handle_dhcpv4(void *addr, void *data, size_t len,
603 struct interface *iface, _unused void *dest_addr)
604 {
605 int sock = iface->dhcpv4_event.uloop.fd;
606
607 dhcpv4_handle_msg(addr, data, len, iface, dest_addr, dhcpv4_send_reply, &sock);
608 }
609
610 void dhcpv4_handle_msg(void *addr, void *data, size_t len,
611 struct interface *iface, _unused void *dest_addr,
612 send_reply_cb_t send_reply, void *opaque)
613 {
614 struct dhcpv4_message *req = data;
615
616 if (iface->dhcpv4 == MODE_DISABLED)
617 return;
618
619 if (len < offsetof(struct dhcpv4_message, options) + 4 ||
620 req->op != DHCPV4_BOOTREQUEST || req->hlen != 6)
621 return;
622
623 syslog(LOG_DEBUG, "Got DHCPv4 request on %s", iface->name);
624
625 if (!iface->dhcpv4_start_ip.s_addr && !iface->dhcpv4_end_ip.s_addr) {
626 syslog(LOG_WARNING, "No DHCP range available on %s", iface->name);
627 return;
628 }
629
630 int sock = iface->dhcpv4_event.uloop.fd;
631
632 struct dhcpv4_message reply = {
633 .op = DHCPV4_BOOTREPLY,
634 .htype = req->htype,
635 .hlen = req->hlen,
636 .hops = 0,
637 .xid = req->xid,
638 .secs = 0,
639 .flags = req->flags,
640 .ciaddr = {INADDR_ANY},
641 .giaddr = req->giaddr,
642 .siaddr = iface->dhcpv4_local,
643 };
644 memcpy(reply.chaddr, req->chaddr, sizeof(reply.chaddr));
645
646 reply.options[0] = 0x63;
647 reply.options[1] = 0x82;
648 reply.options[2] = 0x53;
649 reply.options[3] = 0x63;
650
651 uint8_t *cookie = &reply.options[4];
652 uint8_t reqmsg = DHCPV4_MSG_REQUEST;
653 uint8_t msg = DHCPV4_MSG_ACK;
654
655 uint32_t reqaddr = INADDR_ANY;
656 uint32_t leasetime = 0;
657 size_t hostname_len = 0;
658 size_t reqopts_len = 0;
659 char hostname[256];
660 char reqopts[256];
661 bool accept_fr_nonce = false;
662 bool incl_fr_opt = false;
663
664 uint8_t *start = &req->options[4];
665 uint8_t *end = ((uint8_t*)data) + len;
666 struct dhcpv4_option *opt;
667 dhcpv4_for_each_option(start, end, opt) {
668 if (opt->type == DHCPV4_OPT_MESSAGE && opt->len == 1)
669 reqmsg = opt->data[0];
670 else if (opt->type == DHCPV4_OPT_REQOPTS && opt->len > 0) {
671 reqopts_len = opt->len;
672 memcpy(reqopts, opt->data, reqopts_len);
673 reqopts[reqopts_len] = 0;
674 } else if (opt->type == DHCPV4_OPT_HOSTNAME && opt->len > 0) {
675 hostname_len = opt->len;
676 memcpy(hostname, opt->data, hostname_len);
677 hostname[hostname_len] = 0;
678 } else if (opt->type == DHCPV4_OPT_IPADDRESS && opt->len == 4)
679 memcpy(&reqaddr, opt->data, 4);
680 else if (opt->type == DHCPV4_OPT_SERVERID && opt->len == 4) {
681 if (memcmp(opt->data, &iface->dhcpv4_local, 4))
682 return;
683 } else if (iface->filter_class && opt->type == DHCPV4_OPT_USER_CLASS) {
684 uint8_t *c = opt->data, *cend = &opt->data[opt->len];
685 for (; c < cend && &c[*c] < cend; c = &c[1 + *c]) {
686 size_t elen = strlen(iface->filter_class);
687 if (*c == elen && !memcmp(&c[1], iface->filter_class, elen))
688 return; // Ignore from homenet
689 }
690 } else if (opt->type == DHCPV4_OPT_LEASETIME && opt->len == 4)
691 memcpy(&leasetime, opt->data, 4);
692 else if (opt->type == DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE && opt->len > 0) {
693 for (uint8_t i = 0; i < opt->len; i++) {
694 if (opt->data[i] == 1) {
695 accept_fr_nonce = true;
696 break;
697 }
698 }
699
700 }
701 }
702
703 if (reqmsg != DHCPV4_MSG_DISCOVER && reqmsg != DHCPV4_MSG_REQUEST &&
704 reqmsg != DHCPV4_MSG_INFORM && reqmsg != DHCPV4_MSG_DECLINE &&
705 reqmsg != DHCPV4_MSG_RELEASE)
706 return;
707
708 struct dhcp_assignment *a = NULL;
709 uint32_t serverid = iface->dhcpv4_local.s_addr;
710 uint32_t fr_serverid = INADDR_ANY;
711
712 if (reqmsg != DHCPV4_MSG_INFORM)
713 a = dhcpv4_lease(iface, reqmsg, req->chaddr, reqaddr,
714 &leasetime, hostname, hostname_len,
715 accept_fr_nonce, &incl_fr_opt, &fr_serverid,
716 reqopts, reqopts_len);
717
718 if (!a) {
719 if (reqmsg == DHCPV4_MSG_REQUEST)
720 msg = DHCPV4_MSG_NAK;
721 else if (reqmsg == DHCPV4_MSG_DISCOVER)
722 return;
723 } else if (reqmsg == DHCPV4_MSG_DISCOVER)
724 msg = DHCPV4_MSG_OFFER;
725 else if (reqmsg == DHCPV4_MSG_REQUEST &&
726 ((reqaddr && reqaddr != a->addr) ||
727 (req->ciaddr.s_addr && req->ciaddr.s_addr != a->addr))) {
728 msg = DHCPV4_MSG_NAK;
729 /*
730 * DHCP client requested an IP which we can't offer to him. Probably the
731 * client changed the network or the network has been changed. The reply
732 * type is set to DHCPV4_MSG_NAK, because the client should not use that IP.
733 *
734 * For modern devices we build an answer that includes a valid IP, like
735 * a DHCPV4_MSG_ACK. The client will use that IP and doesn't need to
736 * perform additional DHCP round trips.
737 *
738 */
739
740 /*
741 *
742 * Buggy clients do serverid checking in nack messages; therefore set the
743 * serverid in nack messages triggered by a previous force renew equal to
744 * the server id in use at that time by the server
745 *
746 */
747 if (fr_serverid)
748 serverid = fr_serverid;
749
750 if (req->ciaddr.s_addr &&
751 ((iface->dhcpv4_start_ip.s_addr & iface->dhcpv4_mask.s_addr) !=
752 (req->ciaddr.s_addr & iface->dhcpv4_mask.s_addr)))
753 req->ciaddr.s_addr = INADDR_ANY;
754 }
755
756 syslog(LOG_INFO, "Received %s from %s on %s", dhcpv4_msg_to_string(reqmsg),
757 odhcpd_print_mac(req->chaddr, req->hlen), iface->name);
758
759 #ifdef WITH_UBUS
760 if (reqmsg == DHCPV4_MSG_RELEASE)
761 ubus_bcast_dhcp_event("dhcp.release", req->chaddr, req->hlen,
762 &req->ciaddr, a ? a->hostname : NULL, iface->ifname);
763 #endif
764 if (reqmsg == DHCPV4_MSG_DECLINE || reqmsg == DHCPV4_MSG_RELEASE)
765 return;
766
767 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_MESSAGE, 1, &msg);
768 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_SERVERID, 4, &serverid);
769
770 if (a) {
771 uint32_t val;
772
773 reply.yiaddr.s_addr = a->addr;
774
775 val = htonl(leasetime);
776 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_LEASETIME, 4, &val);
777
778 if (leasetime != UINT32_MAX) {
779 val = htonl(500 * leasetime / 1000);
780 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_RENEW, 4, &val);
781
782 val = htonl(875 * leasetime / 1000);
783 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_REBIND, 4, &val);
784 }
785
786 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_NETMASK, 4,
787 &iface->dhcpv4_mask.s_addr);
788
789 if (a->hostname)
790 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_HOSTNAME,
791 strlen(a->hostname), a->hostname);
792
793 if (iface->dhcpv4_bcast.s_addr != INADDR_ANY)
794 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_BROADCAST, 4, &iface->dhcpv4_bcast);
795
796 if (incl_fr_opt) {
797 if (reqmsg == DHCPV4_MSG_REQUEST) {
798 struct dhcpv4_auth_forcerenew auth = {
799 .protocol = 3,
800 .algorithm = 1,
801 .rdm = 0,
802 .replay = {htonl(time(NULL)), htonl(++serial)},
803 .type = 1,
804 .key = {0},
805 };
806
807 memcpy(auth.key, a->key, sizeof(auth.key));
808 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_AUTHENTICATION, sizeof(auth), &auth);
809 } else {
810 uint8_t one = 1;
811 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE,
812 sizeof(one), &one);
813 }
814 }
815 }
816
817 struct ifreq ifr;
818
819 memset(&ifr, 0, sizeof(ifr));
820 strncpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name) - 1);
821
822 if (!ioctl(sock, SIOCGIFMTU, &ifr)) {
823 uint16_t mtu = htons(ifr.ifr_mtu);
824 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_MTU, 2, &mtu);
825 }
826
827 if (iface->search && iface->search_len <= 255)
828 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_SEARCH_DOMAIN,
829 iface->search_len, iface->search);
830 else if (!res_init() && _res.dnsrch[0] && _res.dnsrch[0][0]) {
831 uint8_t search_buf[256];
832 int len = dn_comp(_res.dnsrch[0], search_buf,
833 sizeof(search_buf), NULL, NULL);
834 if (len > 0)
835 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_SEARCH_DOMAIN,
836 len, search_buf);
837 }
838
839 if (iface->dhcpv4_router_cnt == 0)
840 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_ROUTER, 4, &iface->dhcpv4_local);
841 else
842 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_ROUTER,
843 4 * iface->dhcpv4_router_cnt, iface->dhcpv4_router);
844
845
846 if (iface->dhcpv4_dns_cnt == 0) {
847 if (iface->dns_service)
848 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_DNSSERVER, 4, &iface->dhcpv4_local);
849 } else
850 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_DNSSERVER,
851 4 * iface->dhcpv4_dns_cnt, iface->dhcpv4_dns);
852
853 if (a && a->reqopts && iface->dhcpv4_ntp_cnt != 0) {
854 for(size_t opts = 0; a->reqopts[opts]; opts++) {
855 if (a->reqopts[opts] == DHCPV4_OPT_NTPSERVER) {
856 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_NTPSERVER,
857 4 * iface->dhcpv4_ntp_cnt, iface->dhcpv4_ntp);
858 }
859 }
860 }
861
862 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_END, 0, NULL);
863
864 struct sockaddr_in dest = *((struct sockaddr_in*)addr);
865 if (req->giaddr.s_addr) {
866 /*
867 * relay agent is configured, send reply to the agent
868 */
869 dest.sin_addr = req->giaddr;
870 dest.sin_port = htons(DHCPV4_SERVER_PORT);
871 } else if (req->ciaddr.s_addr && req->ciaddr.s_addr != dest.sin_addr.s_addr) {
872 /*
873 * client has existing configuration (ciaddr is set) AND this address is
874 * not the address it used for the dhcp message
875 */
876 dest.sin_addr = req->ciaddr;
877 dest.sin_port = htons(DHCPV4_CLIENT_PORT);
878 } else if ((ntohs(req->flags) & DHCPV4_FLAG_BROADCAST) ||
879 req->hlen != reply.hlen || !reply.yiaddr.s_addr) {
880 /*
881 * client requests a broadcast reply OR we can't offer an IP
882 */
883 dest.sin_addr.s_addr = INADDR_BROADCAST;
884 dest.sin_port = htons(DHCPV4_CLIENT_PORT);
885 } else if (!req->ciaddr.s_addr && msg == DHCPV4_MSG_NAK) {
886 /*
887 * client has no previous configuration -> no IP, so we need to reply
888 * with a broadcast packet
889 */
890 dest.sin_addr.s_addr = INADDR_BROADCAST;
891 dest.sin_port = htons(DHCPV4_CLIENT_PORT);
892 } else {
893 struct arpreq arp = {.arp_flags = ATF_COM};
894
895 /*
896 * send reply to the newly (in this process) allocated IP
897 */
898 dest.sin_addr = reply.yiaddr;
899 dest.sin_port = htons(DHCPV4_CLIENT_PORT);
900
901 if (!(iface->ifflags & IFF_NOARP)) {
902 memcpy(arp.arp_ha.sa_data, req->chaddr, 6);
903 memcpy(&arp.arp_pa, &dest, sizeof(arp.arp_pa));
904 memcpy(arp.arp_dev, iface->ifname, sizeof(arp.arp_dev));
905
906 if (ioctl(sock, SIOCSARP, &arp) < 0)
907 syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
908 }
909 }
910
911 if (send_reply(&reply, PACKET_SIZE(&reply, cookie),
912 (struct sockaddr*)&dest, sizeof(dest), opaque) < 0)
913 syslog(LOG_ERR, "Failed to send %s to %s - %s: %m",
914 dhcpv4_msg_to_string(msg),
915 dest.sin_addr.s_addr == INADDR_BROADCAST ?
916 "ff:ff:ff:ff:ff:ff": odhcpd_print_mac(req->chaddr, req->hlen),
917 inet_ntoa(dest.sin_addr));
918 else
919 syslog(LOG_DEBUG, "Sent %s to %s - %s",
920 dhcpv4_msg_to_string(msg),
921 dest.sin_addr.s_addr == INADDR_BROADCAST ?
922 "ff:ff:ff:ff:ff:ff": odhcpd_print_mac(req->chaddr, req->hlen),
923 inet_ntoa(dest.sin_addr));
924
925
926 #ifdef WITH_UBUS
927 if (msg == DHCPV4_MSG_ACK)
928 ubus_bcast_dhcp_event("dhcp.ack", req->chaddr, req->hlen, &reply.yiaddr,
929 a ? a->hostname : NULL, iface->ifname);
930 #endif
931 }
932
933 static bool dhcpv4_insert_assignment(struct list_head *list, struct dhcp_assignment *a,
934 uint32_t addr)
935 {
936 uint32_t h_addr = ntohl(addr);
937 struct dhcp_assignment *c;
938
939 list_for_each_entry(c, list, head) {
940 uint32_t c_addr = ntohl(c->addr);
941
942 if (c_addr == h_addr)
943 return false;
944
945 if (c_addr > h_addr)
946 break;
947 }
948
949 /* Insert new node before c (might match list head) */
950 a->addr = addr;
951 list_add_tail(&a->head, &c->head);
952
953 return true;
954 }
955
956 static char* ip4toa(uint32_t addr)
957 {
958 static char buf[16];
959
960 snprintf(buf, sizeof(buf), "%u.%u.%u.%u",
961 ((uint8_t *)&addr)[0], ((uint8_t *)&addr)[1],
962 ((uint8_t *)&addr)[2], ((uint8_t *)&addr)[3]);
963
964 return buf;
965 }
966
967 static bool dhcpv4_assign(struct interface *iface, struct dhcp_assignment *a,
968 uint32_t raddr)
969 {
970 uint32_t start = ntohl(iface->dhcpv4_start_ip.s_addr);
971 uint32_t end = ntohl(iface->dhcpv4_end_ip.s_addr);
972 uint32_t count = end - start + 1;
973 uint32_t seed = 0;
974 bool assigned;
975
976 /* Preconfigured IP address by static lease */
977 if (a->addr) {
978 assigned = dhcpv4_insert_assignment(&iface->dhcpv4_assignments,
979 a, a->addr);
980
981 if (assigned)
982 syslog(LOG_DEBUG, "Assigning static IP: %s", ip4toa(a->addr));
983
984 return assigned;
985 }
986
987 /* try to assign the IP the client asked for */
988 if (start <= ntohl(raddr) && ntohl(raddr) <= end &&
989 !config_find_lease_by_ipaddr(raddr)) {
990 assigned = dhcpv4_insert_assignment(&iface->dhcpv4_assignments,
991 a, raddr);
992
993 if (assigned) {
994 syslog(LOG_DEBUG, "Assigning the IP the client asked for: %s",
995 ip4toa(a->addr));
996
997 return true;
998 }
999 }
1000
1001 /* Seed RNG with checksum of hwaddress */
1002 for (size_t i = 0; i < sizeof(a->hwaddr); ++i) {
1003 /* Knuth's multiplicative method */
1004 uint8_t o = a->hwaddr[i];
1005 seed += (o*2654435761) % UINT32_MAX;
1006 }
1007
1008 srand(seed);
1009
1010 for (uint32_t i = 0, try = (((uint32_t)rand()) % count) + start; i < count;
1011 ++i, try = (((try - start) + 1) % count) + start) {
1012 uint32_t n_try = htonl(try);
1013
1014 if (config_find_lease_by_ipaddr(n_try))
1015 continue;
1016
1017 assigned = dhcpv4_insert_assignment(&iface->dhcpv4_assignments,
1018 a, n_try);
1019
1020 if (assigned) {
1021 syslog(LOG_DEBUG, "Assigning mapped IP: %s (try %u of %u)",
1022 ip4toa(a->addr), i + 1, count);
1023
1024 return true;
1025 }
1026 }
1027
1028 syslog(LOG_NOTICE, "Can't assign any IP address -> address space is full");
1029
1030 return false;
1031 }
1032
1033
1034 static struct dhcp_assignment*
1035 dhcpv4_lease(struct interface *iface, enum dhcpv4_msg msg, const uint8_t *mac,
1036 const uint32_t reqaddr, uint32_t *leasetime, const char *hostname,
1037 const size_t hostname_len, const bool accept_fr_nonce, bool *incl_fr_opt,
1038 uint32_t *fr_serverid, const char* reqopts, const size_t reqopts_len)
1039 {
1040 struct dhcp_assignment *a = find_assignment_by_hwaddr(iface, mac);
1041 struct lease *l = config_find_lease_by_mac(mac);
1042 time_t now = odhcpd_time();
1043
1044 if (l && a && a->lease != l) {
1045 free_assignment(a);
1046 a = NULL;
1047 }
1048
1049 if (a && (a->flags & OAF_BOUND) && a->fr_ip) {
1050 *fr_serverid = a->fr_ip->addr.addr.in.s_addr;
1051 dhcpv4_fr_stop(a);
1052 }
1053
1054 if (msg == DHCPV4_MSG_DISCOVER || msg == DHCPV4_MSG_REQUEST) {
1055 bool assigned = !!a;
1056
1057 if (!a) {
1058 if (!iface->no_dynamic_dhcp || l) {
1059 /* Create new binding */
1060 a = alloc_assignment(0);
1061 if (!a) {
1062 syslog(LOG_WARNING, "Failed to alloc assignment on interface %s",
1063 iface->ifname);
1064 return NULL;
1065 }
1066 memcpy(a->hwaddr, mac, sizeof(a->hwaddr));
1067 /* Set valid time to 0 for static lease indicating */
1068 /* infinite lifetime otherwise current time */
1069 a->valid_until = l ? 0 : now;
1070 a->dhcp_free_cb = dhcpv4_free_assignment;
1071 a->iface = iface;
1072 a->flags = OAF_DHCPV4;
1073 a->addr = l ? l->ipaddr : INADDR_ANY;
1074
1075 assigned = dhcpv4_assign(iface, a, reqaddr);
1076
1077 if (l) {
1078 a->flags |= OAF_STATIC;
1079
1080 if (l->hostname)
1081 a->hostname = strdup(l->hostname);
1082
1083 if (l->leasetime)
1084 a->leasetime = l->leasetime;
1085
1086 list_add(&a->lease_list, &l->assignments);
1087 a->lease = l;
1088 }
1089 }
1090 } else if (((a->addr & iface->dhcpv4_mask.s_addr) !=
1091 (iface->dhcpv4_start_ip.s_addr & iface->dhcpv4_mask.s_addr)) &&
1092 !(a->flags & OAF_STATIC)) {
1093 list_del_init(&a->head);
1094 a->addr = INADDR_ANY;
1095
1096 assigned = dhcpv4_assign(iface, a, reqaddr);
1097 }
1098
1099 if (assigned) {
1100 uint32_t my_leasetime;
1101
1102 if (a->leasetime)
1103 my_leasetime = a->leasetime;
1104 else
1105 my_leasetime = iface->dhcp_leasetime;
1106
1107 if ((*leasetime == 0) || (my_leasetime < *leasetime))
1108 *leasetime = my_leasetime;
1109
1110 if (msg == DHCPV4_MSG_DISCOVER) {
1111 a->flags &= ~OAF_BOUND;
1112
1113 *incl_fr_opt = accept_fr_nonce;
1114 a->valid_until = now;
1115 } else {
1116 if ((!(a->flags & OAF_STATIC) || !a->hostname) && hostname_len > 0) {
1117 a->hostname = realloc(a->hostname, hostname_len + 1);
1118 if (a->hostname) {
1119 memcpy(a->hostname, hostname, hostname_len);
1120 a->hostname[hostname_len] = 0;
1121
1122 if (odhcpd_valid_hostname(a->hostname))
1123 a->flags &= ~OAF_BROKEN_HOSTNAME;
1124 else
1125 a->flags |= OAF_BROKEN_HOSTNAME;
1126 }
1127 }
1128
1129 if (reqopts_len > 0) {
1130 a->reqopts = realloc(a->reqopts, reqopts_len + 1);
1131 if (a->reqopts) {
1132 memcpy(a->reqopts, reqopts, reqopts_len);
1133 a->reqopts[reqopts_len] = 0;
1134 }
1135 }
1136
1137 if (!(a->flags & OAF_BOUND)) {
1138 a->accept_fr_nonce = accept_fr_nonce;
1139 *incl_fr_opt = accept_fr_nonce;
1140 odhcpd_urandom(a->key, sizeof(a->key));
1141 a->flags |= OAF_BOUND;
1142 } else
1143 *incl_fr_opt = false;
1144
1145 a->valid_until = ((*leasetime == UINT32_MAX) ? 0 : (time_t)(now + *leasetime));
1146 }
1147 } else if (!assigned && a) {
1148 /* Cleanup failed assignment */
1149 free_assignment(a);
1150 a = NULL;
1151 }
1152
1153 } else if (msg == DHCPV4_MSG_RELEASE && a) {
1154 a->flags &= ~OAF_BOUND;
1155 a->valid_until = now - 1;
1156
1157 } else if (msg == DHCPV4_MSG_DECLINE && a) {
1158 a->flags &= ~OAF_BOUND;
1159
1160 if (!(a->flags & OAF_STATIC) || a->lease->ipaddr != a->addr) {
1161 memset(a->hwaddr, 0, sizeof(a->hwaddr));
1162 a->valid_until = now + 3600; /* Block address for 1h */
1163 } else
1164 a->valid_until = now - 1;
1165 }
1166
1167 dhcpv6_ia_write_statefile();
1168
1169 return a;
1170 }