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