chiark / gitweb /
sd-dhcp-client: fix REBOOT state handling
[elogind.git] / src / libsystemd-network / sd-dhcp-client.c
1 /***
2   This file is part of systemd.
3
4   Copyright (C) 2013 Intel Corporation. All rights reserved.
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <net/ethernet.h>
25 #include <net/if_arp.h>
26 #include <linux/if_infiniband.h>
27 #include <netinet/ether.h>
28 #include <sys/param.h>
29 #include <sys/ioctl.h>
30
31 #include "util.h"
32 #include "list.h"
33 #include "refcnt.h"
34 #include "async.h"
35
36 #include "dhcp-protocol.h"
37 #include "dhcp-internal.h"
38 #include "dhcp-lease-internal.h"
39 #include "sd-dhcp-client.h"
40
41 #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
42
43 struct sd_dhcp_client {
44         RefCount n_ref;
45
46         DHCPState state;
47         sd_event *event;
48         int event_priority;
49         sd_event_source *timeout_resend;
50         int index;
51         int fd;
52         union sockaddr_union link;
53         sd_event_source *receive_message;
54         bool request_broadcast;
55         uint8_t *req_opts;
56         size_t req_opts_allocated;
57         size_t req_opts_size;
58         be32_t last_addr;
59         struct {
60                 uint8_t type;
61                 struct ether_addr mac_addr;
62         } _packed_ client_id;
63         uint8_t mac_addr[MAX_MAC_ADDR_LEN];
64         size_t mac_addr_len;
65         uint16_t arp_type;
66         char *hostname;
67         char *vendor_class_identifier;
68         uint32_t mtu;
69         uint32_t xid;
70         usec_t start_time;
71         unsigned int attempt;
72         usec_t request_sent;
73         sd_event_source *timeout_t1;
74         sd_event_source *timeout_t2;
75         sd_event_source *timeout_expire;
76         sd_dhcp_client_cb_t cb;
77         void *userdata;
78         sd_dhcp_lease *lease;
79 };
80
81 static const uint8_t default_req_opts[] = {
82         DHCP_OPTION_SUBNET_MASK,
83         DHCP_OPTION_ROUTER,
84         DHCP_OPTION_HOST_NAME,
85         DHCP_OPTION_DOMAIN_NAME,
86         DHCP_OPTION_DOMAIN_NAME_SERVER,
87         DHCP_OPTION_NTP_SERVER,
88 };
89
90 static int client_receive_message_raw(sd_event_source *s, int fd,
91                                       uint32_t revents, void *userdata);
92 static int client_receive_message_udp(sd_event_source *s, int fd,
93                                       uint32_t revents, void *userdata);
94 static void client_stop(sd_dhcp_client *client, int error);
95
96 int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
97                                 void *userdata) {
98         assert_return(client, -EINVAL);
99
100         client->cb = cb;
101         client->userdata = userdata;
102
103         return 0;
104 }
105
106 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
107         assert_return(client, -EINVAL);
108
109         client->request_broadcast = !!broadcast;
110
111         return 0;
112 }
113
114 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
115         size_t i;
116
117         assert_return(client, -EINVAL);
118         assert_return (IN_SET(client->state, DHCP_STATE_INIT,
119                               DHCP_STATE_STOPPED), -EBUSY);
120
121         switch(option) {
122         case DHCP_OPTION_PAD:
123         case DHCP_OPTION_OVERLOAD:
124         case DHCP_OPTION_MESSAGE_TYPE:
125         case DHCP_OPTION_PARAMETER_REQUEST_LIST:
126         case DHCP_OPTION_END:
127                 return -EINVAL;
128
129         default:
130                 break;
131         }
132
133         for (i = 0; i < client->req_opts_size; i++)
134                 if (client->req_opts[i] == option)
135                         return -EEXIST;
136
137         if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
138                             client->req_opts_size + 1))
139                 return -ENOMEM;
140
141         client->req_opts[client->req_opts_size++] = option;
142
143         return 0;
144 }
145
146 int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
147                                        const struct in_addr *last_addr) {
148         assert_return(client, -EINVAL);
149         assert_return (IN_SET(client->state, DHCP_STATE_INIT,
150                               DHCP_STATE_STOPPED), -EBUSY);
151
152         if (last_addr)
153                 client->last_addr = last_addr->s_addr;
154         else
155                 client->last_addr = INADDR_ANY;
156
157         return 0;
158 }
159
160 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
161         assert_return(client, -EINVAL);
162         assert_return (IN_SET(client->state, DHCP_STATE_INIT,
163                               DHCP_STATE_STOPPED), -EBUSY);
164         assert_return(interface_index > 0, -EINVAL);
165
166         client->index = interface_index;
167
168         return 0;
169 }
170
171 int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
172                            size_t addr_len, uint16_t arp_type) {
173         DHCP_CLIENT_DONT_DESTROY(client);
174         bool need_restart = false;
175
176         assert_return(client, -EINVAL);
177         assert_return(addr, -EINVAL);
178         assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
179         assert_return(arp_type > 0, -EINVAL);
180
181         if (arp_type == ARPHRD_ETHER)
182                 assert_return(addr_len == ETH_ALEN, -EINVAL);
183         else if (arp_type == ARPHRD_INFINIBAND)
184                 assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
185         else
186                 return -EINVAL;
187
188         if (client->mac_addr_len == addr_len &&
189             memcmp(&client->mac_addr, addr, addr_len) == 0)
190                 return 0;
191
192         if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
193                 log_dhcp_client(client, "Changing MAC address on running DHCP "
194                                 "client, restarting");
195                 need_restart = true;
196                 client_stop(client, DHCP_EVENT_STOP);
197         }
198
199         memcpy(&client->mac_addr, addr, addr_len);
200         client->mac_addr_len = addr_len;
201         client->arp_type = arp_type;
202
203         memcpy(&client->client_id.mac_addr, addr, ETH_ALEN);
204         client->client_id.type = 0x01;
205
206         if (need_restart && client->state != DHCP_STATE_STOPPED)
207                 sd_dhcp_client_start(client);
208
209         return 0;
210 }
211
212 int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
213                                 const char *hostname) {
214         char *new_hostname = NULL;
215
216         assert_return(client, -EINVAL);
217
218         if (streq_ptr(client->hostname, hostname))
219                 return 0;
220
221         if (hostname) {
222                 new_hostname = strdup(hostname);
223                 if (!new_hostname)
224                         return -ENOMEM;
225         }
226
227         free(client->hostname);
228         client->hostname = new_hostname;
229
230         return 0;
231 }
232
233 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
234                                                const char *vci) {
235         char *new_vci = NULL;
236
237         assert_return(client, -EINVAL);
238
239         new_vci = strdup(vci);
240         if (!new_vci)
241                 return -ENOMEM;
242
243         free(client->vendor_class_identifier);
244
245         client->vendor_class_identifier = new_vci;
246
247         return 0;
248 }
249
250 int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
251         assert_return(client, -EINVAL);
252         assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
253
254         client->mtu = mtu;
255
256         return 0;
257 }
258
259 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
260         assert_return(client, -EINVAL);
261         assert_return(ret, -EINVAL);
262
263         if (client->state != DHCP_STATE_BOUND &&
264             client->state != DHCP_STATE_RENEWING &&
265             client->state != DHCP_STATE_REBINDING)
266                 return -EADDRNOTAVAIL;
267
268         *ret = sd_dhcp_lease_ref(client->lease);
269
270         return 0;
271 }
272
273 static void client_notify(sd_dhcp_client *client, int event) {
274         if (client->cb)
275                 client->cb(client, event, client->userdata);
276 }
277
278 static int client_initialize(sd_dhcp_client *client) {
279         assert_return(client, -EINVAL);
280
281         client->receive_message =
282                 sd_event_source_unref(client->receive_message);
283
284         client->fd = asynchronous_close(client->fd);
285
286         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
287
288         client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
289         client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
290         client->timeout_expire = sd_event_source_unref(client->timeout_expire);
291
292         client->attempt = 1;
293
294         client->state = DHCP_STATE_INIT;
295         client->xid = 0;
296
297         if (client->lease)
298                 client->lease = sd_dhcp_lease_unref(client->lease);
299
300         return 0;
301 }
302
303 static void client_stop(sd_dhcp_client *client, int error) {
304         assert(client);
305
306         if (error < 0)
307                 log_dhcp_client(client, "STOPPED: %s", strerror(-error));
308         else if (error == DHCP_EVENT_STOP)
309                 log_dhcp_client(client, "STOPPED");
310         else
311                 log_dhcp_client(client, "STOPPED: Unknown event");
312
313         client_notify(client, error);
314
315         client_initialize(client);
316 }
317
318 static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
319                                uint8_t type, size_t *_optlen, size_t *_optoffset) {
320         _cleanup_free_ DHCPPacket *packet;
321         size_t optlen, optoffset, size;
322         be16_t max_size;
323         usec_t time_now;
324         uint16_t secs;
325         int r;
326
327         assert(client);
328         assert(client->start_time);
329         assert(ret);
330         assert(_optlen);
331         assert(_optoffset);
332         assert(type == DHCP_DISCOVER || type == DHCP_REQUEST);
333
334         optlen = DHCP_MIN_OPTIONS_SIZE;
335         size = sizeof(DHCPPacket) + optlen;
336
337         packet = malloc0(size);
338         if (!packet)
339                 return -ENOMEM;
340
341         r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
342                               client->arp_type, optlen, &optoffset);
343         if (r < 0)
344                 return r;
345
346         /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
347            refuse to issue an DHCP lease if 'secs' is set to zero */
348         r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
349         if (r < 0)
350                 return r;
351         assert(time_now >= client->start_time);
352
353         /* seconds between sending first and last DISCOVER
354          * must always be strictly positive to deal with broken servers */
355         secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
356         packet->dhcp.secs = htobe16(secs);
357
358         /* RFC2132 section 4.1
359            A client that cannot receive unicast IP datagrams until its protocol
360            software has been configured with an IP address SHOULD set the
361            BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
362            DHCPREQUEST messages that client sends.  The BROADCAST bit will
363            provide a hint to the DHCP server and BOOTP relay agent to broadcast
364            any messages to the client on the client's subnet.
365
366            Note: some interfaces needs this to be enabled, but some networks
367            needs this to be disabled as broadcasts are filteretd, so this
368            needs to be configurable */
369         if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
370                 packet->dhcp.flags = htobe16(0x8000);
371
372         /* RFC2132 section 4.1.1:
373            The client MUST include its hardware address in the ’chaddr’ field, if
374            necessary for delivery of DHCP reply messages.  Non-Ethernet
375            interfaces will leave 'chaddr' empty and use the client identifier
376            instead (eg, RFC 4390 section 2.1).
377          */
378         if (client->arp_type == ARPHRD_ETHER)
379                 memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
380
381         /* Some DHCP servers will refuse to issue an DHCP lease if the Client
382            Identifier option is not set */
383         r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
384                                DHCP_OPTION_CLIENT_IDENTIFIER,
385                                sizeof(client->client_id), &client->client_id);
386         if (r < 0)
387                 return r;
388
389
390         /* RFC2131 section 3.5:
391            in its initial DHCPDISCOVER or DHCPREQUEST message, a
392            client may provide the server with a list of specific
393            parameters the client is interested in. If the client
394            includes a list of parameters in a DHCPDISCOVER message,
395            it MUST include that list in any subsequent DHCPREQUEST
396            messages.
397          */
398         r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
399                                DHCP_OPTION_PARAMETER_REQUEST_LIST,
400                                client->req_opts_size, client->req_opts);
401         if (r < 0)
402                 return r;
403
404         /* RFC2131 section 3.5:
405            The client SHOULD include the ’maximum DHCP message size’ option to
406            let the server know how large the server may make its DHCP messages.
407
408            Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
409            than the defined default size unless the Maximum Messge Size option
410            is explicitely set
411
412            RFC3442 "Requirements to Avoid Sizing Constraints":
413            Because a full routing table can be quite large, the standard 576
414            octet maximum size for a DHCP message may be too short to contain
415            some legitimate Classless Static Route options.  Because of this,
416            clients implementing the Classless Static Route option SHOULD send a
417            Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
418            stack is capable of receiving larger IP datagrams.  In this case, the
419            client SHOULD set the value of this option to at least the MTU of the
420            interface that the client is configuring.  The client MAY set the
421            value of this option higher, up to the size of the largest UDP packet
422            it is prepared to accept.  (Note that the value specified in the
423            Maximum DHCP Message Size option is the total maximum packet size,
424            including IP and UDP headers.)
425          */
426         max_size = htobe16(size);
427         r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
428                                DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
429                                2, &max_size);
430         if (r < 0)
431                 return r;
432
433         *_optlen = optlen;
434         *_optoffset = optoffset;
435         *ret = packet;
436         packet = NULL;
437
438         return 0;
439 }
440
441 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
442                                 size_t len) {
443         dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
444                                       INADDR_BROADCAST, DHCP_PORT_SERVER, len);
445
446         return dhcp_network_send_raw_socket(client->fd, &client->link,
447                                             packet, len);
448 }
449
450 static int client_send_discover(sd_dhcp_client *client) {
451         _cleanup_free_ DHCPPacket *discover = NULL;
452         size_t optoffset, optlen;
453         int r;
454
455         assert(client);
456         assert(client->state == DHCP_STATE_INIT ||
457                client->state == DHCP_STATE_SELECTING);
458
459         r = client_message_init(client, &discover, DHCP_DISCOVER,
460                                 &optlen, &optoffset);
461         if (r < 0)
462                 return r;
463
464         /* the client may suggest values for the network address
465            and lease time in the DHCPDISCOVER message. The client may include
466            the ’requested IP address’ option to suggest that a particular IP
467            address be assigned, and may include the ’IP address lease time’
468            option to suggest the lease time it would like.
469          */
470         if (client->last_addr != INADDR_ANY) {
471                 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
472                                        DHCP_OPTION_REQUESTED_IP_ADDRESS,
473                                        4, &client->last_addr);
474                 if (r < 0)
475                         return r;
476         }
477
478         /* it is unclear from RFC 2131 if client should send hostname in
479            DHCPDISCOVER but dhclient does and so we do as well
480         */
481         if (client->hostname) {
482                 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
483                                        DHCP_OPTION_HOST_NAME,
484                                        strlen(client->hostname), client->hostname);
485                 if (r < 0)
486                         return r;
487         }
488
489         if (client->vendor_class_identifier) {
490                 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
491                                        DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
492                                        strlen(client->vendor_class_identifier),
493                                        client->vendor_class_identifier);
494                 if (r < 0)
495                         return r;
496         }
497
498         r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
499                                DHCP_OPTION_END, 0, NULL);
500         if (r < 0)
501                 return r;
502
503         /* We currently ignore:
504            The client SHOULD wait a random time between one and ten seconds to
505            desynchronize the use of DHCP at startup.
506          */
507         r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
508         if (r < 0)
509                 return r;
510
511         log_dhcp_client(client, "DISCOVER");
512
513         return 0;
514 }
515
516 static int client_send_request(sd_dhcp_client *client) {
517         _cleanup_free_ DHCPPacket *request = NULL;
518         size_t optoffset, optlen;
519         int r;
520
521         r = client_message_init(client, &request, DHCP_REQUEST,
522                                 &optlen, &optoffset);
523         if (r < 0)
524                 return r;
525
526         switch (client->state) {
527         /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
528            SELECTING should be REQUESTING)
529          */
530
531         case DHCP_STATE_REQUESTING:
532                 /* Client inserts the address of the selected server in ’server
533                    identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
534                    filled in with the yiaddr value from the chosen DHCPOFFER.
535                  */
536
537                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
538                                        DHCP_OPTION_SERVER_IDENTIFIER,
539                                        4, &client->lease->server_address);
540                 if (r < 0)
541                         return r;
542
543                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
544                                        DHCP_OPTION_REQUESTED_IP_ADDRESS,
545                                        4, &client->lease->address);
546                 if (r < 0)
547                         return r;
548
549                 break;
550
551         case DHCP_STATE_INIT_REBOOT:
552                 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
553                    option MUST be filled in with client’s notion of its previously
554                    assigned address. ’ciaddr’ MUST be zero.
555                  */
556                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
557                                        DHCP_OPTION_REQUESTED_IP_ADDRESS,
558                                        4, &client->last_addr);
559                 if (r < 0)
560                         return r;
561                 break;
562
563         case DHCP_STATE_RENEWING:
564                 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
565                    option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
566                    client’s IP address.
567                 */
568
569                 /* fall through */
570         case DHCP_STATE_REBINDING:
571                 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
572                    option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
573                    client’s IP address.
574
575                    This message MUST be broadcast to the 0xffffffff IP broadcast address.
576                  */
577                 request->dhcp.ciaddr = client->lease->address;
578
579                 break;
580
581         case DHCP_STATE_INIT:
582         case DHCP_STATE_SELECTING:
583         case DHCP_STATE_REBOOTING:
584         case DHCP_STATE_BOUND:
585         case DHCP_STATE_STOPPED:
586                 return -EINVAL;
587         }
588
589         if (client->hostname) {
590                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
591                                        DHCP_OPTION_HOST_NAME,
592                                        strlen(client->hostname), client->hostname);
593                 if (r < 0)
594                         return r;
595         }
596
597         r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
598                                DHCP_OPTION_END, 0, NULL);
599         if (r < 0)
600                 return r;
601
602         if (client->state == DHCP_STATE_RENEWING) {
603                 r = dhcp_network_send_udp_socket(client->fd,
604                                                  client->lease->server_address,
605                                                  DHCP_PORT_SERVER,
606                                                  &request->dhcp,
607                                                  sizeof(DHCPMessage) + optoffset);
608         } else {
609                 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
610         }
611         if (r < 0)
612                 return r;
613
614         switch (client->state) {
615         case DHCP_STATE_REQUESTING:
616                 log_dhcp_client(client, "REQUEST (requesting)");
617                 break;
618         case DHCP_STATE_INIT_REBOOT:
619                 log_dhcp_client(client, "REQUEST (init-reboot)");
620                 break;
621         case DHCP_STATE_RENEWING:
622                 log_dhcp_client(client, "REQUEST (renewing)");
623                 break;
624         case DHCP_STATE_REBINDING:
625                 log_dhcp_client(client, "REQUEST (rebinding)");
626                 break;
627         default:
628                 log_dhcp_client(client, "REQUEST (invalid)");
629                 break;
630         }
631
632         return 0;
633 }
634
635 static int client_start(sd_dhcp_client *client);
636
637 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
638                                  void *userdata) {
639         sd_dhcp_client *client = userdata;
640         DHCP_CLIENT_DONT_DESTROY(client);
641         usec_t next_timeout = 0;
642         uint64_t time_now;
643         uint32_t time_left;
644         int r;
645
646         assert(s);
647         assert(client);
648         assert(client->event);
649
650         r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
651         if (r < 0)
652                 goto error;
653
654         switch (client->state) {
655         case DHCP_STATE_RENEWING:
656
657                 time_left = (client->lease->t2 - client->lease->t1) / 2;
658                 if (time_left < 60)
659                         time_left = 60;
660
661                 next_timeout = time_now + time_left * USEC_PER_SEC;
662
663                 break;
664
665         case DHCP_STATE_REBINDING:
666
667                 time_left = (client->lease->lifetime - client->lease->t2) / 2;
668                 if (time_left < 60)
669                         time_left = 60;
670
671                 next_timeout = time_now + time_left * USEC_PER_SEC;
672                 break;
673
674         case DHCP_STATE_REBOOTING:
675                 /* start over as we did not receive a timely ack or nak */
676                 r = client_initialize(client);
677                 if (r < 0)
678                         goto error;
679
680                 r = client_start(client);
681                 if (r < 0)
682                         goto error;
683                 else {
684                         log_dhcp_client(client, "REBOOTED");
685                         return 0;
686                 }
687
688         case DHCP_STATE_INIT:
689         case DHCP_STATE_INIT_REBOOT:
690         case DHCP_STATE_SELECTING:
691         case DHCP_STATE_REQUESTING:
692         case DHCP_STATE_BOUND:
693
694                 if (client->attempt < 64)
695                         client->attempt *= 2;
696
697                 next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
698
699                 break;
700
701         case DHCP_STATE_STOPPED:
702                 r = -EINVAL;
703                 goto error;
704         }
705
706         next_timeout += (random_u32() & 0x1fffff);
707
708         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
709
710         r = sd_event_add_time(client->event,
711                               &client->timeout_resend,
712                               clock_boottime_or_monotonic(),
713                               next_timeout, 10 * USEC_PER_MSEC,
714                               client_timeout_resend, client);
715         if (r < 0)
716                 goto error;
717
718         r = sd_event_source_set_priority(client->timeout_resend,
719                                          client->event_priority);
720         if (r < 0)
721                 goto error;
722
723         r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
724         if (r < 0)
725                 goto error;
726
727         switch (client->state) {
728         case DHCP_STATE_INIT:
729                 r = client_send_discover(client);
730                 if (r >= 0) {
731                         client->state = DHCP_STATE_SELECTING;
732                         client->attempt = 1;
733                 } else {
734                         if (client->attempt >= 64)
735                                 goto error;
736                 }
737
738                 break;
739
740         case DHCP_STATE_SELECTING:
741                 r = client_send_discover(client);
742                 if (r < 0 && client->attempt >= 64)
743                         goto error;
744
745                 break;
746
747         case DHCP_STATE_INIT_REBOOT:
748         case DHCP_STATE_REQUESTING:
749         case DHCP_STATE_RENEWING:
750         case DHCP_STATE_REBINDING:
751                 r = client_send_request(client);
752                 if (r < 0 && client->attempt >= 64)
753                          goto error;
754
755                 if (client->state == DHCP_STATE_INIT_REBOOT)
756                         client->state = DHCP_STATE_REBOOTING;
757
758                 client->request_sent = time_now;
759
760                 break;
761
762         case DHCP_STATE_REBOOTING:
763         case DHCP_STATE_BOUND:
764
765                 break;
766
767         case DHCP_STATE_STOPPED:
768                 r = -EINVAL;
769                 goto error;
770         }
771
772         return 0;
773
774 error:
775         client_stop(client, r);
776
777         /* Errors were dealt with when stopping the client, don't spill
778            errors into the event loop handler */
779         return 0;
780 }
781
782 static int client_initialize_io_events(sd_dhcp_client *client,
783                                        sd_event_io_handler_t io_callback) {
784         int r;
785
786         assert(client);
787         assert(client->event);
788
789         r = sd_event_add_io(client->event, &client->receive_message,
790                             client->fd, EPOLLIN, io_callback,
791                             client);
792         if (r < 0)
793                 goto error;
794
795         r = sd_event_source_set_priority(client->receive_message,
796                                          client->event_priority);
797         if (r < 0)
798                 goto error;
799
800         r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
801         if (r < 0)
802                 goto error;
803
804 error:
805         if (r < 0)
806                 client_stop(client, r);
807
808         return 0;
809 }
810
811 static int client_initialize_time_events(sd_dhcp_client *client) {
812         int r;
813
814         assert(client);
815         assert(client->event);
816
817         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
818
819         r = sd_event_add_time(client->event,
820                               &client->timeout_resend,
821                               clock_boottime_or_monotonic(),
822                               0, 0,
823                               client_timeout_resend, client);
824         if (r < 0)
825                 goto error;
826
827         r = sd_event_source_set_priority(client->timeout_resend,
828                                          client->event_priority);
829
830         r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
831         if (r < 0)
832                 goto error;
833
834 error:
835         if (r < 0)
836                 client_stop(client, r);
837
838         return 0;
839
840 }
841
842 static int client_initialize_events(sd_dhcp_client *client,
843                                     sd_event_io_handler_t io_callback) {
844         client_initialize_io_events(client, io_callback);
845         client_initialize_time_events(client);
846
847         return 0;
848 }
849
850 static int client_start(sd_dhcp_client *client) {
851         int r;
852
853         assert_return(client, -EINVAL);
854         assert_return(client->event, -EINVAL);
855         assert_return(client->index > 0, -EINVAL);
856         assert_return(client->fd < 0, -EBUSY);
857         assert_return(client->xid == 0, -EINVAL);
858         assert_return(client->state == DHCP_STATE_INIT ||
859                       client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
860
861         client->xid = random_u32();
862
863         r = dhcp_network_bind_raw_socket(client->index, &client->link,
864                                          client->xid, client->mac_addr,
865                                          client->mac_addr_len, client->arp_type);
866         if (r < 0) {
867                 client_stop(client, r);
868                 return r;
869         }
870         client->fd = r;
871
872         if (client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT)
873                 client->start_time = now(clock_boottime_or_monotonic());
874
875         return client_initialize_events(client, client_receive_message_raw);
876 }
877
878 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
879                                  void *userdata) {
880         sd_dhcp_client *client = userdata;
881         DHCP_CLIENT_DONT_DESTROY(client);
882
883         log_dhcp_client(client, "EXPIRED");
884
885         client_notify(client, DHCP_EVENT_EXPIRED);
886
887         /* lease was lost, start over if not freed or stopped in callback */
888         if (client->state != DHCP_STATE_STOPPED) {
889                 client_initialize(client);
890                 client_start(client);
891         }
892
893         return 0;
894 }
895
896 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
897         sd_dhcp_client *client = userdata;
898         DHCP_CLIENT_DONT_DESTROY(client);
899         int r;
900
901         client->receive_message = sd_event_source_unref(client->receive_message);
902         client->fd = asynchronous_close(client->fd);
903
904         client->state = DHCP_STATE_REBINDING;
905         client->attempt = 1;
906
907         r = dhcp_network_bind_raw_socket(client->index, &client->link,
908                                          client->xid, client->mac_addr,
909                                          client->mac_addr_len, client->arp_type);
910         if (r < 0) {
911                 client_stop(client, r);
912                 return 0;
913         }
914         client->fd = r;
915
916         return client_initialize_events(client, client_receive_message_raw);
917 }
918
919 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
920                              void *userdata) {
921         sd_dhcp_client *client = userdata;
922         DHCP_CLIENT_DONT_DESTROY(client);
923
924         client->state = DHCP_STATE_RENEWING;
925         client->attempt = 1;
926
927         return client_initialize_time_events(client);
928 }
929
930 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
931                                size_t len) {
932         _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
933         int r;
934
935         r = dhcp_lease_new(&lease);
936         if (r < 0)
937                 return r;
938
939         r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
940         if (r != DHCP_OFFER) {
941                 log_dhcp_client(client, "received message was not an OFFER, ignoring");
942                 return -ENOMSG;
943         }
944
945         lease->next_server = offer->siaddr;
946
947         lease->address = offer->yiaddr;
948
949         if (lease->address == INADDR_ANY ||
950             lease->server_address == INADDR_ANY ||
951             lease->lifetime == 0) {
952                 log_dhcp_client(client, "received lease lacks address, server "
953                                 "address or lease lifetime, ignoring");
954                 return -ENOMSG;
955         }
956
957         if (lease->subnet_mask == INADDR_ANY) {
958                 r = dhcp_lease_set_default_subnet_mask(lease);
959                 if (r < 0) {
960                         log_dhcp_client(client, "received lease lacks subnet "
961                                         "mask, and a fallback one can not be "
962                                         "generated, ignoring");
963                         return -ENOMSG;
964                 }
965         }
966
967         sd_dhcp_lease_unref(client->lease);
968         client->lease = lease;
969         lease = NULL;
970
971         log_dhcp_client(client, "OFFER");
972
973         return 0;
974 }
975
976 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
977                                     size_t len) {
978         int r;
979
980         r = dhcp_option_parse(force, len, NULL, NULL);
981         if (r != DHCP_FORCERENEW)
982                 return -ENOMSG;
983
984         log_dhcp_client(client, "FORCERENEW");
985
986         return 0;
987 }
988
989 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
990                              size_t len) {
991         _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
992         int r;
993
994         r = dhcp_lease_new(&lease);
995         if (r < 0)
996                 return r;
997
998         r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
999         if (r == DHCP_NAK) {
1000                 log_dhcp_client(client, "NAK");
1001                 return -EADDRNOTAVAIL;
1002         }
1003
1004         if (r != DHCP_ACK) {
1005                 log_dhcp_client(client, "received message was not an ACK, ignoring");
1006                 return -ENOMSG;
1007         }
1008
1009         lease->next_server = ack->siaddr;
1010
1011         lease->address = ack->yiaddr;
1012
1013         if (lease->address == INADDR_ANY ||
1014             lease->server_address == INADDR_ANY ||
1015             lease->lifetime == 0) {
1016                 log_dhcp_client(client, "received lease lacks address, server "
1017                                 "address or lease lifetime, ignoring");
1018                 return -ENOMSG;
1019         }
1020
1021         if (lease->subnet_mask == INADDR_ANY) {
1022                 r = dhcp_lease_set_default_subnet_mask(lease);
1023                 if (r < 0) {
1024                         log_dhcp_client(client, "received lease lacks subnet "
1025                                         "mask, and a fallback one can not be "
1026                                         "generated, ignoring");
1027                         return -ENOMSG;
1028                 }
1029         }
1030
1031         r = DHCP_EVENT_IP_ACQUIRE;
1032         if (client->lease) {
1033                 if (client->lease->address != lease->address ||
1034                     client->lease->subnet_mask != lease->subnet_mask ||
1035                     client->lease->router != lease->router) {
1036                         r = DHCP_EVENT_IP_CHANGE;
1037                 } else
1038                         r = DHCP_EVENT_RENEW;
1039
1040                 client->lease = sd_dhcp_lease_unref(client->lease);
1041         }
1042
1043         client->lease = lease;
1044         lease = NULL;
1045
1046         log_dhcp_client(client, "ACK");
1047
1048         return r;
1049 }
1050
1051 static uint64_t client_compute_timeout(sd_dhcp_client *client,
1052                                        uint32_t lifetime, double factor) {
1053         assert(client);
1054         assert(client->request_sent);
1055         assert(lifetime);
1056
1057         return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
1058                 + (random_u32() & 0x1fffff);
1059 }
1060
1061 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1062         usec_t time_now;
1063         uint64_t lifetime_timeout;
1064         uint64_t t2_timeout;
1065         uint64_t t1_timeout;
1066         char time_string[FORMAT_TIMESPAN_MAX];
1067         int r;
1068
1069         assert(client);
1070         assert(client->event);
1071         assert(client->lease);
1072         assert(client->lease->lifetime);
1073
1074         client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1075         client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1076         client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1077
1078         /* don't set timers for infinite leases */
1079         if (client->lease->lifetime == 0xffffffff)
1080                 return 0;
1081
1082         r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1083         if (r < 0)
1084                 return r;
1085         assert(client->request_sent <= time_now);
1086
1087         /* convert the various timeouts from relative (secs) to absolute (usecs) */
1088         lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1089         if (client->lease->t1 && client->lease->t2) {
1090                 /* both T1 and T2 are given */
1091                 if (client->lease->t1 < client->lease->t2 &&
1092                     client->lease->t2 < client->lease->lifetime) {
1093                         /* they are both valid */
1094                         t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1095                         t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1096                 } else {
1097                         /* discard both */
1098                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1099                         client->lease->t2 = (client->lease->lifetime * 7) / 8;
1100                         t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1101                         client->lease->t1 = client->lease->lifetime / 2;
1102                 }
1103         } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
1104                 /* only T2 is given, and it is valid */
1105                 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1106                 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1107                 client->lease->t1 = client->lease->lifetime / 2;
1108                 if (t2_timeout <= t1_timeout) {
1109                         /* the computed T1 would be invalid, so discard T2 */
1110                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1111                         client->lease->t2 = (client->lease->lifetime * 7) / 8;
1112                 }
1113         } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
1114                 /* only T1 is given, and it is valid */
1115                 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1116                 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1117                 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1118                 if (t2_timeout <= t1_timeout) {
1119                         /* the computed T2 would be invalid, so discard T1 */
1120                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1121                         client->lease->t2 = client->lease->lifetime / 2;
1122                 }
1123         } else {
1124                 /* fall back to the default timeouts */
1125                 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1126                 client->lease->t1 = client->lease->lifetime / 2;
1127                 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1128                 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1129         }
1130
1131         /* arm lifetime timeout */
1132         r = sd_event_add_time(client->event, &client->timeout_expire,
1133                               clock_boottime_or_monotonic(),
1134                               lifetime_timeout, 10 * USEC_PER_MSEC,
1135                               client_timeout_expire, client);
1136         if (r < 0)
1137                 return r;
1138
1139         r = sd_event_source_set_priority(client->timeout_expire,
1140                                          client->event_priority);
1141         if (r < 0)
1142                 return r;
1143
1144         r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime");
1145         if (r < 0)
1146                 return r;
1147
1148         log_dhcp_client(client, "lease expires in %s",
1149                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1150                         lifetime_timeout - time_now, 0));
1151
1152         /* don't arm earlier timeouts if this has already expired */
1153         if (lifetime_timeout <= time_now)
1154                 return 0;
1155
1156         /* arm T2 timeout */
1157         r = sd_event_add_time(client->event,
1158                               &client->timeout_t2,
1159                               clock_boottime_or_monotonic(),
1160                               t2_timeout,
1161                               10 * USEC_PER_MSEC,
1162                               client_timeout_t2, client);
1163         if (r < 0)
1164                 return r;
1165
1166         r = sd_event_source_set_priority(client->timeout_t2,
1167                                          client->event_priority);
1168         if (r < 0)
1169                 return r;
1170
1171         r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout");
1172         if (r < 0)
1173                 return r;
1174
1175         log_dhcp_client(client, "T2 expires in %s",
1176                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1177                         t2_timeout - time_now, 0));
1178
1179         /* don't arm earlier timeout if this has already expired */
1180         if (t2_timeout <= time_now)
1181                 return 0;
1182
1183         /* arm T1 timeout */
1184         r = sd_event_add_time(client->event,
1185                               &client->timeout_t1,
1186                               clock_boottime_or_monotonic(),
1187                               t1_timeout, 10 * USEC_PER_MSEC,
1188                               client_timeout_t1, client);
1189         if (r < 0)
1190                 return r;
1191
1192         r = sd_event_source_set_priority(client->timeout_t1,
1193                                          client->event_priority);
1194         if (r < 0)
1195                 return r;
1196
1197         r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer");
1198         if (r < 0)
1199                 return r;
1200
1201         log_dhcp_client(client, "T1 expires in %s",
1202                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1203                         t1_timeout - time_now, 0));
1204
1205         return 0;
1206 }
1207
1208 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1209                                  int len) {
1210         DHCP_CLIENT_DONT_DESTROY(client);
1211         int r = 0, notify_event = 0;
1212
1213         assert(client);
1214         assert(client->event);
1215         assert(message);
1216
1217         switch (client->state) {
1218         case DHCP_STATE_SELECTING:
1219
1220                 r = client_handle_offer(client, message, len);
1221                 if (r >= 0) {
1222
1223                         client->timeout_resend =
1224                                 sd_event_source_unref(client->timeout_resend);
1225
1226                         client->state = DHCP_STATE_REQUESTING;
1227                         client->attempt = 1;
1228
1229                         r = sd_event_add_time(client->event,
1230                                               &client->timeout_resend,
1231                                               clock_boottime_or_monotonic(),
1232                                               0, 0,
1233                                               client_timeout_resend, client);
1234                         if (r < 0)
1235                                 goto error;
1236
1237                         r = sd_event_source_set_priority(client->timeout_resend,
1238                                                          client->event_priority);
1239                         if (r < 0)
1240                                 goto error;
1241
1242                         r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
1243                         if (r < 0)
1244                                 goto error;
1245                 } else if (r == -ENOMSG)
1246                         /* invalid message, let's ignore it */
1247                         return 0;
1248
1249                 break;
1250
1251         case DHCP_STATE_REBOOTING:
1252         case DHCP_STATE_REQUESTING:
1253         case DHCP_STATE_RENEWING:
1254         case DHCP_STATE_REBINDING:
1255
1256                 r = client_handle_ack(client, message, len);
1257                 if (r >= 0) {
1258                         client->timeout_resend =
1259                                 sd_event_source_unref(client->timeout_resend);
1260                         client->receive_message =
1261                                 sd_event_source_unref(client->receive_message);
1262                         client->fd = asynchronous_close(client->fd);
1263
1264                         if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1265                                    DHCP_STATE_REBOOTING))
1266                                 notify_event = DHCP_EVENT_IP_ACQUIRE;
1267                         else if (r != DHCP_EVENT_IP_ACQUIRE)
1268                                 notify_event = r;
1269
1270                         client->state = DHCP_STATE_BOUND;
1271                         client->attempt = 1;
1272
1273                         client->last_addr = client->lease->address;
1274
1275                         r = client_set_lease_timeouts(client);
1276                         if (r < 0)
1277                                 goto error;
1278
1279                         r = dhcp_network_bind_udp_socket(client->lease->address,
1280                                                          DHCP_PORT_CLIENT);
1281                         if (r < 0) {
1282                                 log_dhcp_client(client, "could not bind UDP socket");
1283                                 goto error;
1284                         }
1285
1286                         client->fd = r;
1287
1288                         client_initialize_io_events(client, client_receive_message_udp);
1289
1290                         if (notify_event) {
1291                                 client_notify(client, notify_event);
1292                                 if (client->state == DHCP_STATE_STOPPED)
1293                                         return 0;
1294                         }
1295
1296                 } else if (r == -EADDRNOTAVAIL) {
1297                         /* got a NAK, let's restart the client */
1298                         client->timeout_resend =
1299                                 sd_event_source_unref(client->timeout_resend);
1300
1301                         r = client_initialize(client);
1302                         if (r < 0)
1303                                 goto error;
1304
1305                         r = client_start(client);
1306                         if (r < 0)
1307                                 goto error;
1308
1309                         log_dhcp_client(client, "REBOOTED");
1310
1311                         return 0;
1312                 } else if (r == -ENOMSG)
1313                         /* invalid message, let's ignore it */
1314                         return 0;
1315
1316                 break;
1317
1318         case DHCP_STATE_BOUND:
1319                 r = client_handle_forcerenew(client, message, len);
1320                 if (r >= 0) {
1321                         r = client_timeout_t1(NULL, 0, client);
1322                         if (r < 0)
1323                                 goto error;
1324                 } else if (r == -ENOMSG)
1325                         /* invalid message, let's ignore it */
1326                         return 0;
1327
1328                 break;
1329
1330         case DHCP_STATE_INIT:
1331         case DHCP_STATE_INIT_REBOOT:
1332
1333                 break;
1334
1335         case DHCP_STATE_STOPPED:
1336                 r = -EINVAL;
1337                 goto error;
1338         }
1339
1340 error:
1341         if (r < 0)
1342                 client_stop(client, r);
1343
1344         return r;
1345 }
1346
1347 static int client_receive_message_udp(sd_event_source *s, int fd,
1348                                       uint32_t revents, void *userdata) {
1349         sd_dhcp_client *client = userdata;
1350         _cleanup_free_ DHCPMessage *message = NULL;
1351         int buflen = 0, len, r;
1352         const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
1353         const struct ether_addr *expected_chaddr = NULL;
1354         uint8_t expected_hlen = 0;
1355
1356         assert(s);
1357         assert(client);
1358
1359         r = ioctl(fd, FIONREAD, &buflen);
1360         if (r < 0)
1361                 return r;
1362
1363         if (buflen < 0)
1364                 /* this can't be right */
1365                 return -EIO;
1366
1367         message = malloc0(buflen);
1368         if (!message)
1369                 return -ENOMEM;
1370
1371         len = read(fd, message, buflen);
1372         if (len < 0) {
1373                 log_dhcp_client(client, "could not receive message from UDP "
1374                                 "socket: %m");
1375                 return 0;
1376         } else if ((size_t)len < sizeof(DHCPMessage)) {
1377                 log_dhcp_client(client, "too small to be a DHCP message: ignoring");
1378                 return 0;
1379         }
1380
1381         if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1382                 log_dhcp_client(client, "not a DHCP message: ignoring");
1383                 return 0;
1384         }
1385
1386         if (message->op != BOOTREPLY) {
1387                 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1388                 return 0;
1389         }
1390
1391         if (message->htype != client->arp_type) {
1392                 log_dhcp_client(client, "packet type does not match client type");
1393                 return 0;
1394         }
1395
1396         if (client->arp_type == ARPHRD_ETHER) {
1397                 expected_hlen = ETH_ALEN;
1398                 expected_chaddr = (const struct ether_addr *) &client->mac_addr;
1399         } else {
1400                /* Non-ethernet links expect zero chaddr */
1401                expected_hlen = 0;
1402                expected_chaddr = &zero_mac;
1403         }
1404
1405         if (message->hlen != expected_hlen) {
1406                 log_dhcp_client(client, "unexpected packet hlen %d", message->hlen);
1407                 return 0;
1408         }
1409
1410         if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
1411                 log_dhcp_client(client, "received chaddr does not match "
1412                                 "expected: ignoring");
1413                 return 0;
1414         }
1415
1416         if (client->state != DHCP_STATE_BOUND &&
1417             be32toh(message->xid) != client->xid) {
1418                 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1419                    so ignore the xid in this case */
1420                 log_dhcp_client(client, "received xid (%u) does not match "
1421                                 "expected (%u): ignoring",
1422                                 be32toh(message->xid), client->xid);
1423                 return 0;
1424         }
1425
1426         return client_handle_message(client, message, len);
1427 }
1428
1429 static int client_receive_message_raw(sd_event_source *s, int fd,
1430                                       uint32_t revents, void *userdata) {
1431         sd_dhcp_client *client = userdata;
1432         _cleanup_free_ DHCPPacket *packet = NULL;
1433         uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1434         struct iovec iov = {};
1435         struct msghdr msg = {
1436                 .msg_iov = &iov,
1437                 .msg_iovlen = 1,
1438                 .msg_control = cmsgbuf,
1439                 .msg_controllen = sizeof(cmsgbuf),
1440         };
1441         struct cmsghdr *cmsg;
1442         bool checksum = true;
1443         int buflen = 0, len, r;
1444
1445         assert(s);
1446         assert(client);
1447
1448         r = ioctl(fd, FIONREAD, &buflen);
1449         if (r < 0)
1450                 return r;
1451
1452         if (buflen < 0)
1453                 /* this can't be right */
1454                 return -EIO;
1455
1456         packet = malloc0(buflen);
1457         if (!packet)
1458                 return -ENOMEM;
1459
1460         iov.iov_base = packet;
1461         iov.iov_len = buflen;
1462
1463         len = recvmsg(fd, &msg, 0);
1464         if (len < 0) {
1465                 log_dhcp_client(client, "could not receive message from raw "
1466                                 "socket: %m");
1467                 return 0;
1468         } else if ((size_t)len < sizeof(DHCPPacket))
1469                 return 0;
1470
1471         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1472                 if (cmsg->cmsg_level == SOL_PACKET &&
1473                     cmsg->cmsg_type == PACKET_AUXDATA &&
1474                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1475                         struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1476
1477                         checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1478                         break;
1479                 }
1480         }
1481
1482         r = dhcp_packet_verify_headers(packet, len, checksum);
1483         if (r < 0)
1484                 return 0;
1485
1486         len -= DHCP_IP_UDP_SIZE;
1487
1488         return client_handle_message(client, &packet->dhcp, len);
1489 }
1490
1491 int sd_dhcp_client_start(sd_dhcp_client *client) {
1492         int r;
1493
1494         assert_return(client, -EINVAL);
1495
1496         r = client_initialize(client);
1497         if (r < 0)
1498                 return r;
1499
1500         if (client->last_addr)
1501                 client->state = DHCP_STATE_INIT_REBOOT;
1502
1503         r = client_start(client);
1504         if (r >= 0)
1505                 log_dhcp_client(client, "STARTED on ifindex %u", client->index);
1506
1507         return r;
1508 }
1509
1510 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1511         DHCP_CLIENT_DONT_DESTROY(client);
1512
1513         assert_return(client, -EINVAL);
1514
1515         client_stop(client, DHCP_EVENT_STOP);
1516         client->state = DHCP_STATE_STOPPED;
1517
1518         return 0;
1519 }
1520
1521 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1522                                 int priority) {
1523         int r;
1524
1525         assert_return(client, -EINVAL);
1526         assert_return(!client->event, -EBUSY);
1527
1528         if (event)
1529                 client->event = sd_event_ref(event);
1530         else {
1531                 r = sd_event_default(&client->event);
1532                 if (r < 0)
1533                         return 0;
1534         }
1535
1536         client->event_priority = priority;
1537
1538         return 0;
1539 }
1540
1541 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1542         assert_return(client, -EINVAL);
1543
1544         client->event = sd_event_unref(client->event);
1545
1546         return 0;
1547 }
1548
1549 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1550         if (!client)
1551                 return NULL;
1552
1553         return client->event;
1554 }
1555
1556 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1557         if (client)
1558                 assert_se(REFCNT_INC(client->n_ref) >= 2);
1559
1560         return client;
1561 }
1562
1563 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1564         if (client && REFCNT_DEC(client->n_ref) <= 0) {
1565                 log_dhcp_client(client, "FREE");
1566
1567                 client_initialize(client);
1568
1569                 client->receive_message =
1570                         sd_event_source_unref(client->receive_message);
1571
1572                 sd_dhcp_client_detach_event(client);
1573
1574                 sd_dhcp_lease_unref(client->lease);
1575
1576                 free(client->req_opts);
1577                 free(client->hostname);
1578                 free(client->vendor_class_identifier);
1579                 free(client);
1580         }
1581
1582         return NULL;
1583 }
1584
1585 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1586         _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
1587
1588         assert_return(ret, -EINVAL);
1589
1590         client = new0(sd_dhcp_client, 1);
1591         if (!client)
1592                 return -ENOMEM;
1593
1594         client->n_ref = REFCNT_INIT;
1595         client->state = DHCP_STATE_INIT;
1596         client->index = -1;
1597         client->fd = -1;
1598         client->attempt = 1;
1599         client->mtu = DHCP_DEFAULT_MIN_SIZE;
1600
1601         client->req_opts_size = ELEMENTSOF(default_req_opts);
1602
1603         client->req_opts = memdup(default_req_opts, client->req_opts_size);
1604         if (!client->req_opts)
1605                 return -ENOMEM;
1606
1607         *ret = client;
1608         client = NULL;
1609
1610         return 0;
1611 }