]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-dhcp-server.c
dhcp: introduce sd_dhcp_lease_get_timestamp()
[thirdparty/systemd.git] / src / libsystemd-network / sd-dhcp-server.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2013 Intel Corporation. All rights reserved.
4 ***/
5
6 #include <net/if_arp.h>
7 #include <sys/ioctl.h>
8
9 #include "sd-dhcp-server.h"
10 #include "sd-id128.h"
11
12 #include "alloc-util.h"
13 #include "dhcp-internal.h"
14 #include "dhcp-server-internal.h"
15 #include "dns-domain.h"
16 #include "fd-util.h"
17 #include "in-addr-util.h"
18 #include "io-util.h"
19 #include "memory-util.h"
20 #include "network-common.h"
21 #include "ordered-set.h"
22 #include "siphash24.h"
23 #include "string-util.h"
24 #include "unaligned.h"
25 #include "utf8.h"
26
27 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
28 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
29
30 DHCPLease *dhcp_lease_free(DHCPLease *lease) {
31 if (!lease)
32 return NULL;
33
34 if (lease->server) {
35 hashmap_remove_value(lease->server->bound_leases_by_address, UINT32_TO_PTR(lease->address), lease);
36 hashmap_remove_value(lease->server->bound_leases_by_client_id, &lease->client_id, lease);
37 hashmap_remove_value(lease->server->static_leases_by_address, UINT32_TO_PTR(lease->address), lease);
38 hashmap_remove_value(lease->server->static_leases_by_client_id, &lease->client_id, lease);
39 }
40
41 free(lease->client_id.data);
42 free(lease->hostname);
43 return mfree(lease);
44 }
45
46 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
47 * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
48 * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
49 * accidentally hand it out */
50 int sd_dhcp_server_configure_pool(
51 sd_dhcp_server *server,
52 const struct in_addr *address,
53 unsigned char prefixlen,
54 uint32_t offset,
55 uint32_t size) {
56
57 struct in_addr netmask_addr;
58 be32_t netmask;
59 uint32_t server_off, broadcast_off, size_max;
60
61 assert_return(server, -EINVAL);
62 assert_return(address, -EINVAL);
63 assert_return(address->s_addr != INADDR_ANY, -EINVAL);
64 assert_return(prefixlen <= 32, -ERANGE);
65
66 assert_se(in4_addr_prefixlen_to_netmask(&netmask_addr, prefixlen));
67 netmask = netmask_addr.s_addr;
68
69 server_off = be32toh(address->s_addr & ~netmask);
70 broadcast_off = be32toh(~netmask);
71
72 /* the server address cannot be the subnet address */
73 assert_return(server_off != 0, -ERANGE);
74
75 /* nor the broadcast address */
76 assert_return(server_off != broadcast_off, -ERANGE);
77
78 /* 0 offset means we should set a default, we skip the first (subnet) address
79 and take the next one */
80 if (offset == 0)
81 offset = 1;
82
83 size_max = (broadcast_off + 1) /* the number of addresses in the subnet */
84 - offset /* exclude the addresses before the offset */
85 - 1; /* exclude the last (broadcast) address */
86
87 /* The pool must contain at least one address */
88 assert_return(size_max >= 1, -ERANGE);
89
90 if (size != 0)
91 assert_return(size <= size_max, -ERANGE);
92 else
93 size = size_max;
94
95 if (server->address != address->s_addr || server->netmask != netmask || server->pool_size != size || server->pool_offset != offset) {
96
97 server->pool_offset = offset;
98 server->pool_size = size;
99
100 server->address = address->s_addr;
101 server->netmask = netmask;
102 server->subnet = address->s_addr & netmask;
103
104 /* Drop any leases associated with the old address range */
105 hashmap_clear(server->bound_leases_by_address);
106 hashmap_clear(server->bound_leases_by_client_id);
107
108 if (server->callback)
109 server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata);
110 }
111
112 return 0;
113 }
114
115 int sd_dhcp_server_is_running(sd_dhcp_server *server) {
116 assert_return(server, false);
117
118 return !!server->receive_message;
119 }
120
121 int sd_dhcp_server_is_in_relay_mode(sd_dhcp_server *server) {
122 assert_return(server, -EINVAL);
123
124 return in4_addr_is_set(&server->relay_target);
125 }
126
127 void client_id_hash_func(const DHCPClientId *id, struct siphash *state) {
128 assert(id);
129 assert(id->length > 0);
130 assert(id->data);
131
132 siphash24_compress(&id->length, sizeof(id->length), state);
133 siphash24_compress(id->data, id->length, state);
134 }
135
136 int client_id_compare_func(const DHCPClientId *a, const DHCPClientId *b) {
137 int r;
138
139 assert(a->length > 0);
140 assert(a->data);
141 assert(b->length > 0);
142 assert(b->data);
143
144 r = CMP(a->length, b->length);
145 if (r != 0)
146 return r;
147
148 return memcmp(a->data, b->data, a->length);
149 }
150
151 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
152 dhcp_lease_hash_ops,
153 DHCPClientId,
154 client_id_hash_func,
155 client_id_compare_func,
156 DHCPLease,
157 dhcp_lease_free);
158
159 static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
160 assert(server);
161
162 sd_dhcp_server_stop(server);
163
164 sd_event_unref(server->event);
165
166 free(server->boot_server_name);
167 free(server->boot_filename);
168 free(server->timezone);
169
170 for (sd_dhcp_lease_server_type_t i = 0; i < _SD_DHCP_LEASE_SERVER_TYPE_MAX; i++)
171 free(server->servers[i].addr);
172
173 server->bound_leases_by_address = hashmap_free(server->bound_leases_by_address);
174 server->bound_leases_by_client_id = hashmap_free(server->bound_leases_by_client_id);
175 server->static_leases_by_address = hashmap_free(server->static_leases_by_address);
176 server->static_leases_by_client_id = hashmap_free(server->static_leases_by_client_id);
177
178 ordered_set_free(server->extra_options);
179 ordered_set_free(server->vendor_options);
180
181 free(server->agent_circuit_id);
182 free(server->agent_remote_id);
183
184 free(server->ifname);
185 return mfree(server);
186 }
187
188 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_server, sd_dhcp_server, dhcp_server_free);
189
190 int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
191 _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
192
193 assert_return(ret, -EINVAL);
194 assert_return(ifindex > 0, -EINVAL);
195
196 server = new(sd_dhcp_server, 1);
197 if (!server)
198 return -ENOMEM;
199
200 *server = (sd_dhcp_server) {
201 .n_ref = 1,
202 .fd_raw = -EBADF,
203 .fd = -EBADF,
204 .fd_broadcast = -EBADF,
205 .address = htobe32(INADDR_ANY),
206 .netmask = htobe32(INADDR_ANY),
207 .ifindex = ifindex,
208 .bind_to_interface = true,
209 .default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC),
210 .max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC),
211 };
212
213 *ret = TAKE_PTR(server);
214
215 return 0;
216 }
217
218 int sd_dhcp_server_set_ifname(sd_dhcp_server *server, const char *ifname) {
219 assert_return(server, -EINVAL);
220 assert_return(ifname, -EINVAL);
221
222 if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
223 return -EINVAL;
224
225 return free_and_strdup(&server->ifname, ifname);
226 }
227
228 int sd_dhcp_server_get_ifname(sd_dhcp_server *server, const char **ret) {
229 int r;
230
231 assert_return(server, -EINVAL);
232
233 r = get_ifname(server->ifindex, &server->ifname);
234 if (r < 0)
235 return r;
236
237 if (ret)
238 *ret = server->ifname;
239
240 return 0;
241 }
242
243 int sd_dhcp_server_attach_event(sd_dhcp_server *server, sd_event *event, int64_t priority) {
244 int r;
245
246 assert_return(server, -EINVAL);
247 assert_return(!server->event, -EBUSY);
248
249 if (event)
250 server->event = sd_event_ref(event);
251 else {
252 r = sd_event_default(&server->event);
253 if (r < 0)
254 return r;
255 }
256
257 server->event_priority = priority;
258
259 return 0;
260 }
261
262 int sd_dhcp_server_detach_event(sd_dhcp_server *server) {
263 assert_return(server, -EINVAL);
264
265 server->event = sd_event_unref(server->event);
266
267 return 0;
268 }
269
270 sd_event *sd_dhcp_server_get_event(sd_dhcp_server *server) {
271 assert_return(server, NULL);
272
273 return server->event;
274 }
275
276 int sd_dhcp_server_set_boot_server_address(sd_dhcp_server *server, const struct in_addr *address) {
277 assert_return(server, -EINVAL);
278
279 if (address)
280 server->boot_server_address = *address;
281 else
282 server->boot_server_address = (struct in_addr) {};
283
284 return 0;
285 }
286
287 int sd_dhcp_server_set_boot_server_name(sd_dhcp_server *server, const char *name) {
288 int r;
289
290 assert_return(server, -EINVAL);
291
292 if (name) {
293 r = dns_name_is_valid(name);
294 if (r < 0)
295 return r;
296 if (r == 0)
297 return -EINVAL;
298 }
299
300 return free_and_strdup(&server->boot_server_name, name);
301 }
302
303 int sd_dhcp_server_set_boot_filename(sd_dhcp_server *server, const char *filename) {
304 assert_return(server, -EINVAL);
305
306 if (filename && (!string_is_safe(filename) || !ascii_is_valid(filename)))
307 return -EINVAL;
308
309 return free_and_strdup(&server->boot_filename, filename);
310 }
311
312 int sd_dhcp_server_stop(sd_dhcp_server *server) {
313 bool running;
314
315 if (!server)
316 return 0;
317
318 running = sd_dhcp_server_is_running(server);
319
320 server->receive_message = sd_event_source_disable_unref(server->receive_message);
321 server->receive_broadcast = sd_event_source_disable_unref(server->receive_broadcast);
322
323 server->fd_raw = safe_close(server->fd_raw);
324 server->fd = safe_close(server->fd);
325 server->fd_broadcast = safe_close(server->fd_broadcast);
326
327 if (running)
328 log_dhcp_server(server, "STOPPED");
329
330 return 0;
331 }
332
333 static int dhcp_server_send_unicast_raw(
334 sd_dhcp_server *server,
335 uint8_t hlen,
336 const uint8_t *chaddr,
337 DHCPPacket *packet,
338 size_t len) {
339
340 union sockaddr_union link = {
341 .ll.sll_family = AF_PACKET,
342 .ll.sll_protocol = htobe16(ETH_P_IP),
343 .ll.sll_ifindex = server->ifindex,
344 .ll.sll_halen = hlen,
345 };
346
347 assert(server);
348 assert(server->ifindex > 0);
349 assert(server->address != 0);
350 assert(hlen > 0);
351 assert(chaddr);
352 assert(packet);
353 assert(len > sizeof(DHCPPacket));
354
355 memcpy(link.ll.sll_addr, chaddr, hlen);
356
357 if (len > UINT16_MAX)
358 return -EOVERFLOW;
359
360 dhcp_packet_append_ip_headers(packet, server->address, DHCP_PORT_SERVER,
361 packet->dhcp.yiaddr,
362 DHCP_PORT_CLIENT, len, -1);
363
364 return dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len);
365 }
366
367 static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
368 uint16_t destination_port,
369 DHCPMessage *message, size_t len) {
370 union sockaddr_union dest = {
371 .in.sin_family = AF_INET,
372 .in.sin_port = htobe16(destination_port),
373 .in.sin_addr.s_addr = destination,
374 };
375 struct iovec iov = {
376 .iov_base = message,
377 .iov_len = len,
378 };
379 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo))) control = {};
380 struct msghdr msg = {
381 .msg_name = &dest,
382 .msg_namelen = sizeof(dest.in),
383 .msg_iov = &iov,
384 .msg_iovlen = 1,
385 };
386 struct cmsghdr *cmsg;
387 struct in_pktinfo *pktinfo;
388
389 assert(server);
390 assert(server->fd >= 0);
391 assert(message);
392 assert(len >= sizeof(DHCPMessage));
393
394 if (server->bind_to_interface) {
395 msg.msg_control = &control;
396 msg.msg_controllen = sizeof(control);
397
398 cmsg = CMSG_FIRSTHDR(&msg);
399 assert(cmsg);
400
401 cmsg->cmsg_level = IPPROTO_IP;
402 cmsg->cmsg_type = IP_PKTINFO;
403 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
404
405 /* we attach source interface and address info to the message
406 rather than binding the socket. This will be mostly useful
407 when we gain support for arbitrary number of server addresses
408 */
409 pktinfo = CMSG_TYPED_DATA(cmsg, struct in_pktinfo);
410 assert(pktinfo);
411
412 pktinfo->ipi_ifindex = server->ifindex;
413 pktinfo->ipi_spec_dst.s_addr = server->address;
414 }
415
416 if (sendmsg(server->fd, &msg, 0) < 0)
417 return -errno;
418
419 return 0;
420 }
421
422 static bool requested_broadcast(DHCPMessage *message) {
423 assert(message);
424 return message->flags & htobe16(0x8000);
425 }
426
427 static int dhcp_server_send(
428 sd_dhcp_server *server,
429 uint8_t hlen,
430 const uint8_t *chaddr,
431 be32_t destination,
432 uint16_t destination_port,
433 DHCPPacket *packet,
434 size_t optoffset,
435 bool l2_broadcast) {
436
437 if (destination != INADDR_ANY)
438 return dhcp_server_send_udp(server, destination,
439 destination_port, &packet->dhcp,
440 sizeof(DHCPMessage) + optoffset);
441 else if (l2_broadcast)
442 return dhcp_server_send_udp(server, INADDR_BROADCAST,
443 destination_port, &packet->dhcp,
444 sizeof(DHCPMessage) + optoffset);
445 else
446 /* we cannot send UDP packet to specific MAC address when the
447 address is not yet configured, so must fall back to raw
448 packets */
449 return dhcp_server_send_unicast_raw(server, hlen, chaddr, packet,
450 sizeof(DHCPPacket) + optoffset);
451 }
452
453 int dhcp_server_send_packet(sd_dhcp_server *server,
454 DHCPRequest *req, DHCPPacket *packet,
455 int type, size_t optoffset) {
456 be32_t destination = INADDR_ANY;
457 uint16_t destination_port = DHCP_PORT_CLIENT;
458 int r;
459
460 assert(server);
461 assert(req);
462 assert(req->max_optlen > 0);
463 assert(req->message);
464 assert(optoffset <= req->max_optlen);
465 assert(packet);
466
467 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0,
468 SD_DHCP_OPTION_SERVER_IDENTIFIER,
469 4, &server->address);
470 if (r < 0)
471 return r;
472
473 if (req->agent_info_option) {
474 size_t opt_full_length = *(req->agent_info_option + 1) + 2;
475 /* there must be space left for SD_DHCP_OPTION_END */
476 if (optoffset + opt_full_length < req->max_optlen) {
477 memcpy(packet->dhcp.options + optoffset, req->agent_info_option, opt_full_length);
478 optoffset += opt_full_length;
479 }
480 }
481
482 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0,
483 SD_DHCP_OPTION_END, 0, NULL);
484 if (r < 0)
485 return r;
486
487 /* RFC 2131 Section 4.1
488
489 If the ’giaddr’ field in a DHCP message from a client is non-zero,
490 the server sends any return messages to the ’DHCP server’ port on the
491 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
492 field is zero and the ’ciaddr’ field is nonzero, then the server
493 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
494 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
495 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
496 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
497 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
498 messages to the client’s hardware address and ’yiaddr’ address. In
499 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
500 messages to 0xffffffff.
501
502 Section 4.3.2
503
504 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
505 different subnet. The server MUST set the broadcast bit in the
506 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
507 client, because the client may not have a correct network address
508 or subnet mask, and the client may not be answering ARP requests.
509 */
510 if (req->message->giaddr != 0) {
511 destination = req->message->giaddr;
512 destination_port = DHCP_PORT_SERVER;
513 if (type == DHCP_NAK)
514 packet->dhcp.flags = htobe16(0x8000);
515 } else if (req->message->ciaddr != 0 && type != DHCP_NAK)
516 destination = req->message->ciaddr;
517
518 bool l2_broadcast = requested_broadcast(req->message) || type == DHCP_NAK;
519 return dhcp_server_send(server, req->message->hlen, req->message->chaddr,
520 destination, destination_port, packet, optoffset, l2_broadcast);
521 }
522
523 static int server_message_init(
524 sd_dhcp_server *server,
525 DHCPPacket **ret,
526 uint8_t type,
527 size_t *ret_optoffset,
528 DHCPRequest *req) {
529
530 _cleanup_free_ DHCPPacket *packet = NULL;
531 size_t optoffset = 0;
532 int r;
533
534 assert(server);
535 assert(ret);
536 assert(ret_optoffset);
537 assert(IN_SET(type, DHCP_OFFER, DHCP_ACK, DHCP_NAK));
538 assert(req);
539
540 packet = malloc0(sizeof(DHCPPacket) + req->max_optlen);
541 if (!packet)
542 return -ENOMEM;
543
544 r = dhcp_message_init(&packet->dhcp, BOOTREPLY,
545 be32toh(req->message->xid), type,
546 req->message->htype, req->message->hlen, req->message->chaddr,
547 req->max_optlen, &optoffset);
548 if (r < 0)
549 return r;
550
551 packet->dhcp.flags = req->message->flags;
552 packet->dhcp.giaddr = req->message->giaddr;
553
554 *ret_optoffset = optoffset;
555 *ret = TAKE_PTR(packet);
556
557 return 0;
558 }
559
560 static int server_send_offer_or_ack(
561 sd_dhcp_server *server,
562 DHCPRequest *req,
563 be32_t address,
564 uint8_t type) {
565
566 static const uint8_t option_map[_SD_DHCP_LEASE_SERVER_TYPE_MAX] = {
567 [SD_DHCP_LEASE_DNS] = SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
568 [SD_DHCP_LEASE_NTP] = SD_DHCP_OPTION_NTP_SERVER,
569 [SD_DHCP_LEASE_SIP] = SD_DHCP_OPTION_SIP_SERVER,
570 [SD_DHCP_LEASE_POP3] = SD_DHCP_OPTION_POP3_SERVER,
571 [SD_DHCP_LEASE_SMTP] = SD_DHCP_OPTION_SMTP_SERVER,
572 [SD_DHCP_LEASE_LPR] = SD_DHCP_OPTION_LPR_SERVER,
573 };
574
575 _cleanup_free_ DHCPPacket *packet = NULL;
576 sd_dhcp_option *j;
577 be32_t lease_time;
578 size_t offset;
579 int r;
580
581 assert(server);
582 assert(req);
583 assert(IN_SET(type, DHCP_OFFER, DHCP_ACK));
584
585 r = server_message_init(server, &packet, type, &offset, req);
586 if (r < 0)
587 return r;
588
589 packet->dhcp.yiaddr = address;
590 packet->dhcp.siaddr = server->boot_server_address.s_addr;
591
592 lease_time = htobe32(req->lifetime);
593 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
594 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
595 &lease_time);
596 if (r < 0)
597 return r;
598
599 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
600 SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
601 if (r < 0)
602 return r;
603
604 if (server->emit_router) {
605 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
606 SD_DHCP_OPTION_ROUTER, 4,
607 in4_addr_is_set(&server->router_address) ?
608 &server->router_address.s_addr :
609 &server->address);
610 if (r < 0)
611 return r;
612 }
613
614 if (server->boot_server_name) {
615 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
616 SD_DHCP_OPTION_BOOT_SERVER_NAME,
617 strlen(server->boot_server_name), server->boot_server_name);
618 if (r < 0)
619 return r;
620 }
621
622 if (server->boot_filename) {
623 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
624 SD_DHCP_OPTION_BOOT_FILENAME,
625 strlen(server->boot_filename), server->boot_filename);
626 if (r < 0)
627 return r;
628 }
629
630 for (sd_dhcp_lease_server_type_t k = 0; k < _SD_DHCP_LEASE_SERVER_TYPE_MAX; k++) {
631 if (server->servers[k].size <= 0)
632 continue;
633
634 r = dhcp_option_append(
635 &packet->dhcp, req->max_optlen, &offset, 0,
636 option_map[k],
637 sizeof(struct in_addr) * server->servers[k].size,
638 server->servers[k].addr);
639 if (r < 0)
640 return r;
641 }
642
643 if (server->timezone) {
644 r = dhcp_option_append(
645 &packet->dhcp, req->max_optlen, &offset, 0,
646 SD_DHCP_OPTION_TZDB_TIMEZONE,
647 strlen(server->timezone), server->timezone);
648 if (r < 0)
649 return r;
650 }
651
652 ORDERED_SET_FOREACH(j, server->extra_options) {
653 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
654 j->option, j->length, j->data);
655 if (r < 0)
656 return r;
657 }
658
659 if (!ordered_set_isempty(server->vendor_options)) {
660 r = dhcp_option_append(
661 &packet->dhcp, req->max_optlen, &offset, 0,
662 SD_DHCP_OPTION_VENDOR_SPECIFIC,
663 ordered_set_size(server->vendor_options), server->vendor_options);
664 if (r < 0)
665 return r;
666 }
667
668 return dhcp_server_send_packet(server, req, packet, type, offset);
669 }
670
671 static int server_send_nak_or_ignore(sd_dhcp_server *server, bool init_reboot, DHCPRequest *req) {
672 _cleanup_free_ DHCPPacket *packet = NULL;
673 size_t offset;
674 int r;
675
676 /* When a request is refused, RFC 2131, section 4.3.2 mentioned we should send NAK when the
677 * client is in INITREBOOT. If the client is in other state, there is nothing mentioned in the
678 * RFC whether we should send NAK or not. Hence, let's silently ignore the request. */
679
680 if (!init_reboot)
681 return 0;
682
683 r = server_message_init(server, &packet, DHCP_NAK, &offset, req);
684 if (r < 0)
685 return log_dhcp_server_errno(server, r, "Failed to create NAK message: %m");
686
687 r = dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset);
688 if (r < 0)
689 return log_dhcp_server_errno(server, r, "Could not send NAK message: %m");
690
691 log_dhcp_server(server, "NAK (0x%x)", be32toh(req->message->xid));
692 return DHCP_NAK;
693 }
694
695 static int server_send_forcerenew(
696 sd_dhcp_server *server,
697 be32_t address,
698 be32_t gateway,
699 uint8_t htype,
700 uint8_t hlen,
701 const uint8_t *chaddr) {
702
703 _cleanup_free_ DHCPPacket *packet = NULL;
704 size_t optoffset = 0;
705 int r;
706
707 assert(server);
708 assert(address != INADDR_ANY);
709 assert(chaddr);
710
711 packet = malloc0(sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE);
712 if (!packet)
713 return -ENOMEM;
714
715 r = dhcp_message_init(&packet->dhcp, BOOTREPLY, 0,
716 DHCP_FORCERENEW, htype, hlen, chaddr,
717 DHCP_MIN_OPTIONS_SIZE, &optoffset);
718 if (r < 0)
719 return r;
720
721 r = dhcp_option_append(&packet->dhcp, DHCP_MIN_OPTIONS_SIZE,
722 &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL);
723 if (r < 0)
724 return r;
725
726 return dhcp_server_send_udp(server, address, DHCP_PORT_CLIENT,
727 &packet->dhcp,
728 sizeof(DHCPMessage) + optoffset);
729 }
730
731 static int parse_request(uint8_t code, uint8_t len, const void *option, void *userdata) {
732 DHCPRequest *req = ASSERT_PTR(userdata);
733 int r;
734
735 switch (code) {
736 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
737 if (len == 4)
738 req->lifetime = unaligned_read_be32(option);
739
740 break;
741 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS:
742 if (len == 4)
743 memcpy(&req->requested_ip, option, sizeof(be32_t));
744
745 break;
746 case SD_DHCP_OPTION_SERVER_IDENTIFIER:
747 if (len == 4)
748 memcpy(&req->server_id, option, sizeof(be32_t));
749
750 break;
751 case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
752 if (len >= 2) {
753 uint8_t *data;
754
755 data = memdup(option, len);
756 if (!data)
757 return -ENOMEM;
758
759 free_and_replace(req->client_id.data, data);
760 req->client_id.length = len;
761 }
762
763 break;
764 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE:
765
766 if (len == 2 && unaligned_read_be16(option) >= sizeof(DHCPPacket))
767 req->max_optlen = unaligned_read_be16(option) - sizeof(DHCPPacket);
768
769 break;
770 case SD_DHCP_OPTION_RELAY_AGENT_INFORMATION:
771 req->agent_info_option = (uint8_t*)option - 2;
772
773 break;
774 case SD_DHCP_OPTION_HOST_NAME:
775 r = dhcp_option_parse_string(option, len, &req->hostname);
776 if (r < 0) {
777 log_debug_errno(r, "Failed to parse hostname, ignoring: %m");
778 return 0;
779 }
780
781 break;
782 }
783
784 return 0;
785 }
786
787 static DHCPRequest* dhcp_request_free(DHCPRequest *req) {
788 if (!req)
789 return NULL;
790
791 free(req->client_id.data);
792 free(req->hostname);
793 return mfree(req);
794 }
795
796 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free);
797
798 static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMessage *message) {
799 assert(req);
800 assert(message);
801
802 req->message = message;
803
804 if (message->hlen > sizeof(message->chaddr))
805 return -EBADMSG;
806
807 /* set client id based on MAC address if client did not send an explicit one */
808 if (!req->client_id.data) {
809 uint8_t *data;
810
811 if (message->hlen == 0)
812 return -EBADMSG;
813
814 data = new0(uint8_t, message->hlen + 1);
815 if (!data)
816 return -ENOMEM;
817
818 data[0] = 0x01;
819 memcpy(data + 1, message->chaddr, message->hlen);
820
821 req->client_id.length = message->hlen + 1;
822 req->client_id.data = data;
823 }
824
825 if (message->hlen == 0 || memeqzero(message->chaddr, message->hlen)) {
826 /* See RFC2131 section 4.1.1.
827 * hlen and chaddr may not be set for non-ethernet interface.
828 * Let's try to retrieve it from the client ID. */
829
830 if (!req->client_id.data)
831 return -EBADMSG;
832
833 if (req->client_id.length <= 1 || req->client_id.length > sizeof(message->chaddr) + 1)
834 return -EBADMSG;
835
836 if (req->client_id.data[0] != 0x01)
837 return -EBADMSG;
838
839 message->hlen = req->client_id.length - 1;
840 memcpy(message->chaddr, req->client_id.data + 1, message->hlen);
841 }
842
843 if (req->max_optlen < DHCP_MIN_OPTIONS_SIZE)
844 req->max_optlen = DHCP_MIN_OPTIONS_SIZE;
845
846 if (req->lifetime <= 0)
847 req->lifetime = MAX(1ULL, server->default_lease_time);
848
849 if (server->max_lease_time > 0 && req->lifetime > server->max_lease_time)
850 req->lifetime = server->max_lease_time;
851
852 return 0;
853 }
854
855 static bool address_is_in_pool(sd_dhcp_server *server, be32_t address) {
856 assert(server);
857
858 if (server->pool_size == 0)
859 return false;
860
861 if (address == server->address)
862 return false;
863
864 if (be32toh(address) < (be32toh(server->subnet) | server->pool_offset) ||
865 be32toh(address) >= (be32toh(server->subnet) | (server->pool_offset + server->pool_size)))
866 return false;
867
868 if (hashmap_contains(server->static_leases_by_address, UINT32_TO_PTR(address)))
869 return false;
870
871 return true;
872 }
873
874 static int append_agent_information_option(sd_dhcp_server *server, DHCPMessage *message, size_t opt_length, size_t size) {
875 int r;
876 size_t offset;
877
878 assert(server);
879 assert(message);
880
881 r = dhcp_option_find_option(message->options, opt_length, SD_DHCP_OPTION_END, &offset);
882 if (r < 0)
883 return r;
884
885 r = dhcp_option_append(message, size, &offset, 0, SD_DHCP_OPTION_RELAY_AGENT_INFORMATION, 0, server);
886 if (r < 0)
887 return r;
888
889 r = dhcp_option_append(message, size, &offset, 0, SD_DHCP_OPTION_END, 0, NULL);
890 if (r < 0)
891 return r;
892 return offset;
893 }
894
895 static int dhcp_server_relay_message(sd_dhcp_server *server, DHCPMessage *message, size_t opt_length, size_t buflen) {
896 _cleanup_free_ DHCPPacket *packet = NULL;
897 int r;
898
899 assert(server);
900 assert(message);
901 assert(sd_dhcp_server_is_in_relay_mode(server));
902
903 if (message->hlen == 0 || message->hlen > sizeof(message->chaddr) || memeqzero(message->chaddr, message->hlen))
904 return log_dhcp_server_errno(server, SYNTHETIC_ERRNO(EBADMSG),
905 "(relay agent) received message without/invalid hardware address, discarding.");
906
907 if (message->op == BOOTREQUEST) {
908 log_dhcp_server(server, "(relay agent) BOOTREQUEST (0x%x)", be32toh(message->xid));
909 if (message->hops >= 16)
910 return -ETIME;
911 message->hops++;
912
913 /* https://tools.ietf.org/html/rfc1542#section-4.1.1 */
914 if (message->giaddr == 0)
915 message->giaddr = server->address;
916
917 if (server->agent_circuit_id || server->agent_remote_id) {
918 r = append_agent_information_option(server, message, opt_length, buflen - sizeof(DHCPMessage));
919 if (r < 0)
920 return log_dhcp_server_errno(server, r, "could not append relay option: %m");
921 opt_length = r;
922 }
923
924 return dhcp_server_send_udp(server, server->relay_target.s_addr, DHCP_PORT_SERVER, message, sizeof(DHCPMessage) + opt_length);
925 } else if (message->op == BOOTREPLY) {
926 log_dhcp_server(server, "(relay agent) BOOTREPLY (0x%x)", be32toh(message->xid));
927 if (message->giaddr != server->address)
928 return log_dhcp_server_errno(server, SYNTHETIC_ERRNO(EBADMSG),
929 "(relay agent) BOOTREPLY giaddr mismatch, discarding");
930
931 int message_type = dhcp_option_parse(message, sizeof(DHCPMessage) + opt_length, NULL, NULL, NULL);
932 if (message_type < 0)
933 return message_type;
934
935 packet = malloc0(sizeof(DHCPPacket) + opt_length);
936 if (!packet)
937 return -ENOMEM;
938 memcpy(&packet->dhcp, message, sizeof(DHCPMessage) + opt_length);
939
940 r = dhcp_option_remove_option(packet->dhcp.options, opt_length, SD_DHCP_OPTION_RELAY_AGENT_INFORMATION);
941 if (r > 0)
942 opt_length = r;
943
944 bool l2_broadcast = requested_broadcast(message) || message_type == DHCP_NAK;
945 const be32_t destination = message_type == DHCP_NAK ? INADDR_ANY : message->ciaddr;
946 return dhcp_server_send(server, message->hlen, message->chaddr, destination, DHCP_PORT_CLIENT, packet, opt_length, l2_broadcast);
947 }
948 return -EBADMSG;
949 }
950
951 static int prepare_new_lease(DHCPLease **ret_lease, be32_t address, DHCPRequest *req, usec_t expiration) {
952 _cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL;
953
954 assert(ret_lease);
955 assert(address != 0);
956 assert(req);
957 assert(expiration != 0);
958
959 lease = new(DHCPLease, 1);
960 if (!lease)
961 return -ENOMEM;
962
963 *lease = (DHCPLease) {
964 .address = address,
965 .client_id.length = req->client_id.length,
966 .htype = req->message->htype,
967 .hlen = req->message->hlen,
968 .gateway = req->message->giaddr,
969 .expiration = expiration,
970 };
971 lease->client_id.data = memdup(req->client_id.data, req->client_id.length);
972 if (!lease->client_id.data)
973 return -ENOMEM;
974
975 memcpy(lease->chaddr, req->message->chaddr, req->message->hlen);
976
977 if (req->hostname) {
978 lease->hostname = strdup(req->hostname);
979 if (!lease->hostname)
980 return -ENOMEM;
981 }
982
983 *ret_lease = TAKE_PTR(lease);
984
985 return 0;
986 }
987
988 static int server_ack_request(sd_dhcp_server *server, DHCPRequest *req, DHCPLease *existing_lease, be32_t address) {
989 usec_t time_now, expiration;
990 int r;
991
992 assert(server);
993 assert(req);
994 assert(address != 0);
995
996 r = sd_event_now(server->event, CLOCK_BOOTTIME, &time_now);
997 if (r < 0)
998 return r;
999
1000 expiration = usec_add(req->lifetime * USEC_PER_SEC, time_now);
1001
1002 if (existing_lease) {
1003 assert(existing_lease->server);
1004 assert(existing_lease->address == address);
1005 existing_lease->expiration = expiration;
1006
1007 } else {
1008 _cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL;
1009
1010 r = prepare_new_lease(&lease, address, req, expiration);
1011 if (r < 0)
1012 return log_dhcp_server_errno(server, r, "Failed to create new lease: %m");
1013
1014 lease->server = server; /* This must be set just before hashmap_put(). */
1015
1016 r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease);
1017 if (r < 0)
1018 return log_dhcp_server_errno(server, r, "Could not save lease: %m");
1019
1020 r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease);
1021 if (r < 0)
1022 return log_dhcp_server_errno(server, r, "Could not save lease: %m");
1023
1024 TAKE_PTR(lease);
1025 }
1026
1027 r = server_send_offer_or_ack(server, req, address, DHCP_ACK);
1028 if (r < 0)
1029 return log_dhcp_server_errno(server, r, "Could not send ACK: %m");
1030
1031 log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid));
1032
1033 if (server->callback)
1034 server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata);
1035
1036 return DHCP_ACK;
1037 }
1038
1039 static int dhcp_server_cleanup_expired_leases(sd_dhcp_server *server) {
1040 DHCPLease *lease;
1041 usec_t time_now;
1042 int r;
1043
1044 assert(server);
1045
1046 r = sd_event_now(server->event, CLOCK_BOOTTIME, &time_now);
1047 if (r < 0)
1048 return r;
1049
1050 HASHMAP_FOREACH(lease, server->bound_leases_by_client_id)
1051 if (lease->expiration < time_now) {
1052 log_dhcp_server(server, "CLEAN (0x%x)", be32toh(lease->address));
1053 dhcp_lease_free(lease);
1054 }
1055
1056 return 0;
1057 }
1058
1059 static bool address_available(sd_dhcp_server *server, be32_t address) {
1060 assert(server);
1061
1062 if (hashmap_contains(server->bound_leases_by_address, UINT32_TO_PTR(address)) ||
1063 hashmap_contains(server->static_leases_by_address, UINT32_TO_PTR(address)) ||
1064 address == server->address)
1065 return false;
1066
1067 return true;
1068 }
1069
1070 static int server_get_static_lease(sd_dhcp_server *server, const DHCPRequest *req, DHCPLease **ret) {
1071 DHCPLease *static_lease;
1072 _cleanup_free_ uint8_t *data = NULL;
1073
1074 assert(server);
1075 assert(req);
1076 assert(ret);
1077
1078 static_lease = hashmap_get(server->static_leases_by_client_id, &req->client_id);
1079 if (static_lease) {
1080 *ret = static_lease;
1081 return 0;
1082 }
1083
1084 /* when no lease is found based on the client id fall back to chaddr */
1085 data = new(uint8_t, req->message->hlen + 1);
1086 if (!data)
1087 return -ENOMEM;
1088
1089 /* set client id type to 1: Ethernet Link-Layer (RFC 2132) */
1090 data[0] = 0x01;
1091 memcpy(data + 1, req->message->chaddr, req->message->hlen);
1092
1093 static_lease = hashmap_get(server->static_leases_by_client_id,
1094 &(DHCPClientId) {
1095 .length = req->message->hlen + 1,
1096 .data = data,
1097 });
1098
1099 *ret = static_lease;
1100
1101 return 0;
1102 }
1103
1104 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
1105
1106 int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, size_t length) {
1107 _cleanup_(dhcp_request_freep) DHCPRequest *req = NULL;
1108 _cleanup_free_ char *error_message = NULL;
1109 DHCPLease *existing_lease, *static_lease;
1110 int type, r;
1111
1112 assert(server);
1113 assert(message);
1114
1115 if (message->op != BOOTREQUEST)
1116 return 0;
1117
1118 req = new0(DHCPRequest, 1);
1119 if (!req)
1120 return -ENOMEM;
1121
1122 type = dhcp_option_parse(message, length, parse_request, req, &error_message);
1123 if (type < 0)
1124 return type;
1125
1126 r = ensure_sane_request(server, req, message);
1127 if (r < 0)
1128 return r;
1129
1130 r = dhcp_server_cleanup_expired_leases(server);
1131 if (r < 0)
1132 return r;
1133
1134 existing_lease = hashmap_get(server->bound_leases_by_client_id, &req->client_id);
1135 r = server_get_static_lease(server, req, &static_lease);
1136 if (r < 0)
1137 return r;
1138
1139 switch (type) {
1140
1141 case DHCP_DISCOVER: {
1142 be32_t address = INADDR_ANY;
1143
1144 log_dhcp_server(server, "DISCOVER (0x%x)", be32toh(req->message->xid));
1145
1146 if (server->pool_size == 0)
1147 /* no pool allocated */
1148 return 0;
1149
1150 /* for now pick a random free address from the pool */
1151 if (static_lease)
1152 address = static_lease->address;
1153 else if (existing_lease)
1154 address = existing_lease->address;
1155 else {
1156 struct siphash state;
1157 uint64_t hash;
1158
1159 /* even with no persistence of leases, we try to offer the same client
1160 the same IP address. we do this by using the hash of the client id
1161 as the offset into the pool of leases when finding the next free one */
1162
1163 siphash24_init(&state, HASH_KEY.bytes);
1164 client_id_hash_func(&req->client_id, &state);
1165 hash = htole64(siphash24_finalize(&state));
1166
1167 for (unsigned i = 0; i < server->pool_size; i++) {
1168 be32_t tmp_address;
1169
1170 tmp_address = server->subnet | htobe32(server->pool_offset + (hash + i) % server->pool_size);
1171 if (address_available(server, tmp_address)) {
1172 address = tmp_address;
1173 break;
1174 }
1175 }
1176 }
1177
1178 if (address == INADDR_ANY)
1179 /* no free addresses left */
1180 return 0;
1181
1182 r = server_send_offer_or_ack(server, req, address, DHCP_OFFER);
1183 if (r < 0)
1184 /* this only fails on critical errors */
1185 return log_dhcp_server_errno(server, r, "Could not send offer: %m");
1186
1187 log_dhcp_server(server, "OFFER (0x%x)", be32toh(req->message->xid));
1188 return DHCP_OFFER;
1189 }
1190 case DHCP_DECLINE:
1191 log_dhcp_server(server, "DECLINE (0x%x): %s", be32toh(req->message->xid), strna(error_message));
1192
1193 /* TODO: make sure we don't offer this address again */
1194
1195 return 1;
1196
1197 case DHCP_REQUEST: {
1198 be32_t address;
1199 bool init_reboot = false;
1200
1201 /* see RFC 2131, section 4.3.2 */
1202
1203 if (req->server_id != 0) {
1204 log_dhcp_server(server, "REQUEST (selecting) (0x%x)",
1205 be32toh(req->message->xid));
1206
1207 /* SELECTING */
1208 if (req->server_id != server->address)
1209 /* client did not pick us */
1210 return 0;
1211
1212 if (req->message->ciaddr != 0)
1213 /* this MUST be zero */
1214 return 0;
1215
1216 if (req->requested_ip == 0)
1217 /* this must be filled in with the yiaddr
1218 from the chosen OFFER */
1219 return 0;
1220
1221 address = req->requested_ip;
1222 } else if (req->requested_ip != 0) {
1223 log_dhcp_server(server, "REQUEST (init-reboot) (0x%x)",
1224 be32toh(req->message->xid));
1225
1226 /* INIT-REBOOT */
1227 if (req->message->ciaddr != 0)
1228 /* this MUST be zero */
1229 return 0;
1230
1231 /* TODO: check more carefully if IP is correct */
1232 address = req->requested_ip;
1233 init_reboot = true;
1234 } else {
1235 log_dhcp_server(server, "REQUEST (rebinding/renewing) (0x%x)",
1236 be32toh(req->message->xid));
1237
1238 /* REBINDING / RENEWING */
1239 if (req->message->ciaddr == 0)
1240 /* this MUST be filled in with clients IP address */
1241 return 0;
1242
1243 address = req->message->ciaddr;
1244 }
1245
1246 /* disallow our own address */
1247 if (address == server->address)
1248 return 0;
1249
1250 if (static_lease) {
1251 /* Found a static lease for the client ID. */
1252
1253 if (static_lease->address != address)
1254 /* The client requested an address which is different from the static lease. Refuse. */
1255 return server_send_nak_or_ignore(server, init_reboot, req);
1256
1257 return server_ack_request(server, req, existing_lease, address);
1258 }
1259
1260 if (address_is_in_pool(server, address)) {
1261 /* The requested address is in the pool. */
1262
1263 if (existing_lease && existing_lease->address != address)
1264 /* We previously assigned an address, but the client requested another one. Refuse. */
1265 return server_send_nak_or_ignore(server, init_reboot, req);
1266
1267 return server_ack_request(server, req, existing_lease, address);
1268 }
1269
1270 return server_send_nak_or_ignore(server, init_reboot, req);
1271 }
1272
1273 case DHCP_RELEASE: {
1274 log_dhcp_server(server, "RELEASE (0x%x)",
1275 be32toh(req->message->xid));
1276
1277 if (!existing_lease)
1278 return 0;
1279
1280 if (existing_lease->address != req->message->ciaddr)
1281 return 0;
1282
1283 dhcp_lease_free(existing_lease);
1284
1285 if (server->callback)
1286 server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata);
1287
1288 return 0;
1289 }}
1290
1291 return 0;
1292 }
1293
1294 static size_t relay_agent_information_length(const char* agent_circuit_id, const char* agent_remote_id) {
1295 size_t sum = 0;
1296 if (agent_circuit_id)
1297 sum += 2 + strlen(agent_circuit_id);
1298 if (agent_remote_id)
1299 sum += 2 + strlen(agent_remote_id);
1300 return sum;
1301 }
1302
1303 static int server_receive_message(sd_event_source *s, int fd,
1304 uint32_t revents, void *userdata) {
1305 _cleanup_free_ DHCPMessage *message = NULL;
1306 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo))) control;
1307 sd_dhcp_server *server = ASSERT_PTR(userdata);
1308 struct iovec iov = {};
1309 struct msghdr msg = {
1310 .msg_iov = &iov,
1311 .msg_iovlen = 1,
1312 .msg_control = &control,
1313 .msg_controllen = sizeof(control),
1314 };
1315 ssize_t datagram_size, len;
1316 int r;
1317
1318 datagram_size = next_datagram_size_fd(fd);
1319 if (ERRNO_IS_NEG_TRANSIENT(datagram_size) || ERRNO_IS_NEG_DISCONNECT(datagram_size))
1320 return 0;
1321 if (datagram_size < 0) {
1322 log_dhcp_server_errno(server, datagram_size, "Failed to determine datagram size to read, ignoring: %m");
1323 return 0;
1324 }
1325
1326 size_t buflen = datagram_size;
1327 if (sd_dhcp_server_is_in_relay_mode(server))
1328 /* Preallocate the additional size for DHCP Relay Agent Information Option if needed */
1329 buflen += relay_agent_information_length(server->agent_circuit_id, server->agent_remote_id) + 2;
1330
1331 message = malloc(buflen);
1332 if (!message)
1333 return -ENOMEM;
1334
1335 iov = IOVEC_MAKE(message, datagram_size);
1336
1337 len = recvmsg_safe(fd, &msg, 0);
1338 if (ERRNO_IS_NEG_TRANSIENT(len) || ERRNO_IS_NEG_DISCONNECT(len))
1339 return 0;
1340 if (len < 0) {
1341 log_dhcp_server_errno(server, len, "Could not receive message, ignoring: %m");
1342 return 0;
1343 }
1344
1345 if ((size_t) len < sizeof(DHCPMessage))
1346 return 0;
1347
1348 /* TODO figure out if this can be done as a filter on the socket, like for IPv6 */
1349 struct in_pktinfo *info = CMSG_FIND_DATA(&msg, IPPROTO_IP, IP_PKTINFO, struct in_pktinfo);
1350 if (info && info->ipi_ifindex != server->ifindex)
1351 return 0;
1352
1353 if (sd_dhcp_server_is_in_relay_mode(server)) {
1354 r = dhcp_server_relay_message(server, message, len - sizeof(DHCPMessage), buflen);
1355 if (r < 0)
1356 log_dhcp_server_errno(server, r, "Couldn't relay message, ignoring: %m");
1357 } else {
1358 r = dhcp_server_handle_message(server, message, (size_t) len);
1359 if (r < 0)
1360 log_dhcp_server_errno(server, r, "Couldn't process incoming message, ignoring: %m");
1361 }
1362 return 0;
1363 }
1364
1365 static void dhcp_server_update_lease_servers(sd_dhcp_server *server) {
1366 assert(server);
1367 assert(server->address != 0);
1368
1369 /* Convert null address -> server address */
1370
1371 for (sd_dhcp_lease_server_type_t k = 0; k < _SD_DHCP_LEASE_SERVER_TYPE_MAX; k++)
1372 for (size_t i = 0; i < server->servers[k].size; i++)
1373 if (in4_addr_is_null(&server->servers[k].addr[i]))
1374 server->servers[k].addr[i].s_addr = server->address;
1375 }
1376
1377 int sd_dhcp_server_start(sd_dhcp_server *server) {
1378 int r;
1379
1380 assert_return(server, -EINVAL);
1381 assert_return(server->event, -EINVAL);
1382
1383 if (sd_dhcp_server_is_running(server))
1384 return 0;
1385
1386 assert_return(!server->receive_message, -EBUSY);
1387 assert_return(server->fd_raw < 0, -EBUSY);
1388 assert_return(server->fd < 0, -EBUSY);
1389 assert_return(server->address != htobe32(INADDR_ANY), -EUNATCH);
1390
1391 dhcp_server_update_lease_servers(server);
1392
1393 r = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
1394 if (r < 0) {
1395 r = -errno;
1396 goto on_error;
1397 }
1398 server->fd_raw = r;
1399
1400 if (server->bind_to_interface)
1401 r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_ANY, DHCP_PORT_SERVER, -1);
1402 else
1403 r = dhcp_network_bind_udp_socket(0, server->address, DHCP_PORT_SERVER, -1);
1404 if (r < 0)
1405 goto on_error;
1406 server->fd = r;
1407
1408 r = sd_event_add_io(server->event, &server->receive_message,
1409 server->fd, EPOLLIN,
1410 server_receive_message, server);
1411 if (r < 0)
1412 goto on_error;
1413
1414 r = sd_event_source_set_priority(server->receive_message,
1415 server->event_priority);
1416 if (r < 0)
1417 goto on_error;
1418
1419 if (!server->bind_to_interface) {
1420 r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_BROADCAST, DHCP_PORT_SERVER, -1);
1421 if (r < 0)
1422 goto on_error;
1423
1424 server->fd_broadcast = r;
1425
1426 r = sd_event_add_io(server->event, &server->receive_broadcast,
1427 server->fd_broadcast, EPOLLIN,
1428 server_receive_message, server);
1429 if (r < 0)
1430 goto on_error;
1431
1432 r = sd_event_source_set_priority(server->receive_broadcast,
1433 server->event_priority);
1434 if (r < 0)
1435 goto on_error;
1436 }
1437
1438 log_dhcp_server(server, "STARTED");
1439
1440 return 0;
1441
1442 on_error:
1443 sd_dhcp_server_stop(server);
1444 return r;
1445 }
1446
1447 int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
1448 DHCPLease *lease;
1449 int r = 0;
1450
1451 assert_return(server, -EINVAL);
1452
1453 log_dhcp_server(server, "FORCERENEW");
1454
1455 HASHMAP_FOREACH(lease, server->bound_leases_by_client_id)
1456 RET_GATHER(r,
1457 server_send_forcerenew(server, lease->address, lease->gateway,
1458 lease->htype, lease->hlen, lease->chaddr));
1459 return r;
1460 }
1461
1462 int sd_dhcp_server_set_bind_to_interface(sd_dhcp_server *server, int enabled) {
1463 assert_return(server, -EINVAL);
1464 assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
1465
1466 if (!!enabled == server->bind_to_interface)
1467 return 0;
1468
1469 server->bind_to_interface = enabled;
1470
1471 return 1;
1472 }
1473
1474 int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *tz) {
1475 int r;
1476
1477 assert_return(server, -EINVAL);
1478 assert_return(timezone_is_valid(tz, LOG_DEBUG), -EINVAL);
1479
1480 if (streq_ptr(tz, server->timezone))
1481 return 0;
1482
1483 r = free_and_strdup(&server->timezone, tz);
1484 if (r < 0)
1485 return r;
1486
1487 return 1;
1488 }
1489
1490 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t) {
1491 assert_return(server, -EINVAL);
1492
1493 if (t == server->max_lease_time)
1494 return 0;
1495
1496 server->max_lease_time = t;
1497 return 1;
1498 }
1499
1500 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t) {
1501 assert_return(server, -EINVAL);
1502
1503 if (t == server->default_lease_time)
1504 return 0;
1505
1506 server->default_lease_time = t;
1507 return 1;
1508 }
1509
1510 int sd_dhcp_server_set_servers(
1511 sd_dhcp_server *server,
1512 sd_dhcp_lease_server_type_t what,
1513 const struct in_addr addresses[],
1514 size_t n_addresses) {
1515
1516 struct in_addr *c = NULL;
1517
1518 assert_return(server, -EINVAL);
1519 assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
1520 assert_return(addresses || n_addresses == 0, -EINVAL);
1521 assert_return(what >= 0, -EINVAL);
1522 assert_return(what < _SD_DHCP_LEASE_SERVER_TYPE_MAX, -EINVAL);
1523
1524 if (server->servers[what].size == n_addresses &&
1525 memcmp(server->servers[what].addr, addresses, sizeof(struct in_addr) * n_addresses) == 0)
1526 return 0;
1527
1528 if (n_addresses > 0) {
1529 c = newdup(struct in_addr, addresses, n_addresses);
1530 if (!c)
1531 return -ENOMEM;
1532 }
1533
1534 free_and_replace(server->servers[what].addr, c);
1535 server->servers[what].size = n_addresses;
1536 return 1;
1537 }
1538
1539 int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], size_t n) {
1540 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_DNS, dns, n);
1541 }
1542 int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], size_t n) {
1543 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_NTP, ntp, n);
1544 }
1545 int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], size_t n) {
1546 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_SIP, sip, n);
1547 }
1548 int sd_dhcp_server_set_pop3(sd_dhcp_server *server, const struct in_addr pop3[], size_t n) {
1549 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_POP3, pop3, n);
1550 }
1551 int sd_dhcp_server_set_smtp(sd_dhcp_server *server, const struct in_addr smtp[], size_t n) {
1552 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_SMTP, smtp, n);
1553 }
1554 int sd_dhcp_server_set_lpr(sd_dhcp_server *server, const struct in_addr lpr[], size_t n) {
1555 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_LPR, lpr, n);
1556 }
1557
1558 int sd_dhcp_server_set_router(sd_dhcp_server *server, const struct in_addr *router) {
1559 assert_return(server, -EINVAL);
1560
1561 /* router is NULL: router option will not be appended.
1562 * router is null address (0.0.0.0): the server address will be used as the router address.
1563 * otherwise: the specified address will be used as the router address. */
1564
1565 server->emit_router = router;
1566 if (router)
1567 server->router_address = *router;
1568
1569 return 0;
1570 }
1571
1572 int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v) {
1573 int r;
1574
1575 assert_return(server, -EINVAL);
1576 assert_return(v, -EINVAL);
1577
1578 r = ordered_set_ensure_put(&server->extra_options, &dhcp_option_hash_ops, v);
1579 if (r < 0)
1580 return r;
1581
1582 sd_dhcp_option_ref(v);
1583 return 0;
1584 }
1585
1586 int sd_dhcp_server_add_vendor_option(sd_dhcp_server *server, sd_dhcp_option *v) {
1587 int r;
1588
1589 assert_return(server, -EINVAL);
1590 assert_return(v, -EINVAL);
1591
1592 r = ordered_set_ensure_put(&server->vendor_options, &dhcp_option_hash_ops, v);
1593 if (r < 0)
1594 return r;
1595
1596 sd_dhcp_option_ref(v);
1597
1598 return 1;
1599 }
1600
1601 int sd_dhcp_server_set_callback(sd_dhcp_server *server, sd_dhcp_server_callback_t cb, void *userdata) {
1602 assert_return(server, -EINVAL);
1603
1604 server->callback = cb;
1605 server->callback_userdata = userdata;
1606
1607 return 0;
1608 }
1609
1610 int sd_dhcp_server_set_relay_target(sd_dhcp_server *server, const struct in_addr *address) {
1611 assert_return(server, -EINVAL);
1612 assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
1613
1614 if (memcmp(address, &server->relay_target, sizeof(struct in_addr)) == 0)
1615 return 0;
1616
1617 server->relay_target = *address;
1618 return 1;
1619 }
1620
1621 int sd_dhcp_server_set_relay_agent_information(
1622 sd_dhcp_server *server,
1623 const char *agent_circuit_id,
1624 const char *agent_remote_id) {
1625 _cleanup_free_ char *circuit_id_dup = NULL, *remote_id_dup = NULL;
1626
1627 assert_return(server, -EINVAL);
1628
1629 if (relay_agent_information_length(agent_circuit_id, agent_remote_id) > UINT8_MAX)
1630 return -ENOBUFS;
1631
1632 if (agent_circuit_id) {
1633 circuit_id_dup = strdup(agent_circuit_id);
1634 if (!circuit_id_dup)
1635 return -ENOMEM;
1636 }
1637
1638 if (agent_remote_id) {
1639 remote_id_dup = strdup(agent_remote_id);
1640 if (!remote_id_dup)
1641 return -ENOMEM;
1642 }
1643
1644 free_and_replace(server->agent_circuit_id, circuit_id_dup);
1645 free_and_replace(server->agent_remote_id, remote_id_dup);
1646 return 0;
1647 }
1648
1649 int sd_dhcp_server_set_static_lease(
1650 sd_dhcp_server *server,
1651 const struct in_addr *address,
1652 uint8_t *client_id,
1653 size_t client_id_size) {
1654
1655 _cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL;
1656 int r;
1657
1658 assert_return(server, -EINVAL);
1659 assert_return(client_id, -EINVAL);
1660 assert_return(client_id_size > 0, -EINVAL);
1661 assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
1662
1663 /* Static lease with an empty or omitted address is a valid entry,
1664 * the server removes any static lease with the specified mac address. */
1665 if (!address || address->s_addr == 0) {
1666 DHCPClientId c;
1667
1668 c = (DHCPClientId) {
1669 .length = client_id_size,
1670 .data = client_id,
1671 };
1672
1673 dhcp_lease_free(hashmap_get(server->static_leases_by_client_id, &c));
1674 return 0;
1675 }
1676
1677 lease = new(DHCPLease, 1);
1678 if (!lease)
1679 return -ENOMEM;
1680
1681 *lease = (DHCPLease) {
1682 .address = address->s_addr,
1683 .client_id.length = client_id_size,
1684 };
1685 lease->client_id.data = memdup(client_id, client_id_size);
1686 if (!lease->client_id.data)
1687 return -ENOMEM;
1688
1689 lease->server = server; /* This must be set just before hashmap_put(). */
1690
1691 r = hashmap_ensure_put(&server->static_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease);
1692 if (r < 0)
1693 return r;
1694 r = hashmap_ensure_put(&server->static_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease);
1695 if (r < 0)
1696 return r;
1697
1698 TAKE_PTR(lease);
1699 return 0;
1700 }