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