chiark / gitweb /
sd-dhcp-client: allow the max dhcp message size to be set to the MTU of the link
[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         switch (client->state) {
704         case DHCP_STATE_INIT:
705                 r = client_send_discover(client);
706                 if (r >= 0) {
707                         client->state = DHCP_STATE_SELECTING;
708                         client->attempt = 1;
709                 } else {
710                         if (client->attempt >= 64)
711                                 goto error;
712                 }
713
714                 break;
715
716         case DHCP_STATE_SELECTING:
717                 r = client_send_discover(client);
718                 if (r < 0 && client->attempt >= 64)
719                         goto error;
720
721                 break;
722
723         case DHCP_STATE_INIT_REBOOT:
724         case DHCP_STATE_REQUESTING:
725         case DHCP_STATE_RENEWING:
726         case DHCP_STATE_REBINDING:
727                 r = client_send_request(client);
728                 if (r < 0 && client->attempt >= 64)
729                          goto error;
730
731                 if (client->state == DHCP_STATE_INIT_REBOOT)
732                         client->state = DHCP_STATE_REBOOTING;
733
734                 client->request_sent = time_now;
735
736                 break;
737
738         case DHCP_STATE_REBOOTING:
739         case DHCP_STATE_BOUND:
740
741                 break;
742
743         case DHCP_STATE_STOPPED:
744                 r = -EINVAL;
745                 goto error;
746         }
747
748         return 0;
749
750 error:
751         client_stop(client, r);
752
753         /* Errors were dealt with when stopping the client, don't spill
754            errors into the event loop handler */
755         return 0;
756 }
757
758 static int client_initialize_io_events(sd_dhcp_client *client,
759                                        sd_event_io_handler_t io_callback) {
760         int r;
761
762         assert(client);
763         assert(client->event);
764
765         r = sd_event_add_io(client->event, &client->receive_message,
766                             client->fd, EPOLLIN, io_callback,
767                             client);
768         if (r < 0)
769                 goto error;
770
771         r = sd_event_source_set_priority(client->receive_message,
772                                          client->event_priority);
773         if (r < 0)
774                 goto error;
775
776 error:
777         if (r < 0)
778                 client_stop(client, r);
779
780         return 0;
781 }
782
783 static int client_initialize_time_events(sd_dhcp_client *client) {
784         int r;
785
786         assert(client);
787         assert(client->event);
788
789         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
790
791         r = sd_event_add_time(client->event,
792                               &client->timeout_resend,
793                               clock_boottime_or_monotonic(),
794                               0, 0,
795                               client_timeout_resend, client);
796         if (r < 0)
797                 goto error;
798
799         r = sd_event_source_set_priority(client->timeout_resend,
800                                          client->event_priority);
801
802 error:
803         if (r < 0)
804                 client_stop(client, r);
805
806         return 0;
807
808 }
809
810 static int client_initialize_events(sd_dhcp_client *client,
811                                     sd_event_io_handler_t io_callback) {
812         client_initialize_io_events(client, io_callback);
813         client_initialize_time_events(client);
814
815         return 0;
816 }
817
818 static int client_start(sd_dhcp_client *client) {
819         int r;
820
821         assert_return(client, -EINVAL);
822         assert_return(client->event, -EINVAL);
823         assert_return(client->index > 0, -EINVAL);
824         assert_return(client->fd < 0, -EBUSY);
825         assert_return(client->xid == 0, -EINVAL);
826         assert_return(client->state == DHCP_STATE_INIT ||
827                       client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
828
829         client->xid = random_u32();
830
831         r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
832         if (r < 0) {
833                 client_stop(client, r);
834                 return r;
835         }
836         client->fd = r;
837
838         if (client->state == DHCP_STATE_INIT) {
839                 client->start_time = now(clock_boottime_or_monotonic());
840                 client->secs = 0;
841         }
842
843         return client_initialize_events(client, client_receive_message_raw);
844 }
845
846 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
847                                  void *userdata) {
848         sd_dhcp_client *client = userdata;
849         DHCP_CLIENT_DONT_DESTROY(client);
850
851         log_dhcp_client(client, "EXPIRED");
852
853         client_notify(client, DHCP_EVENT_EXPIRED);
854
855         /* lease was lost, start over if not freed or stopped in callback */
856         if (client->state != DHCP_STATE_STOPPED) {
857                 client_initialize(client);
858                 client_start(client);
859         }
860
861         return 0;
862 }
863
864 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
865         sd_dhcp_client *client = userdata;
866         DHCP_CLIENT_DONT_DESTROY(client);
867         int r;
868
869         client->receive_message = sd_event_source_unref(client->receive_message);
870         client->fd = asynchronous_close(client->fd);
871
872         client->state = DHCP_STATE_REBINDING;
873         client->attempt = 1;
874
875         r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
876         if (r < 0) {
877                 client_stop(client, r);
878                 return 0;
879         }
880         client->fd = r;
881
882         return client_initialize_events(client, client_receive_message_raw);
883 }
884
885 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
886                              void *userdata) {
887         sd_dhcp_client *client = userdata;
888         DHCP_CLIENT_DONT_DESTROY(client);
889
890         client->state = DHCP_STATE_RENEWING;
891         client->attempt = 1;
892
893         return client_initialize_time_events(client);
894 }
895
896 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
897                                size_t len) {
898         _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
899         int r;
900
901         r = dhcp_lease_new(&lease);
902         if (r < 0)
903                 return r;
904
905         r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
906         if (r != DHCP_OFFER) {
907                 log_dhcp_client(client, "receieved message was not an OFFER, ignoring");
908                 return -ENOMSG;
909         }
910
911         lease->next_server = offer->siaddr;
912
913         lease->address = offer->yiaddr;
914
915         if (lease->address == INADDR_ANY ||
916             lease->server_address == INADDR_ANY ||
917             lease->lifetime == 0) {
918                 log_dhcp_client(client, "receieved lease lacks address, server "
919                                 "address or lease lifetime, ignoring");
920                 return -ENOMSG;
921         }
922
923         if (lease->subnet_mask == INADDR_ANY) {
924                 r = dhcp_lease_set_default_subnet_mask(lease);
925                 if (r < 0) {
926                         log_dhcp_client(client, "receieved lease lacks subnet "
927                                         "mask, and a fallback one can not be "
928                                         "generated, ignoring");
929                         return -ENOMSG;
930                 }
931         }
932
933         sd_dhcp_lease_unref(client->lease);
934         client->lease = lease;
935         lease = NULL;
936
937         log_dhcp_client(client, "OFFER");
938
939         return 0;
940 }
941
942 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
943                                     size_t len) {
944         int r;
945
946         r = dhcp_option_parse(force, len, NULL, NULL);
947         if (r != DHCP_FORCERENEW)
948                 return -ENOMSG;
949
950         log_dhcp_client(client, "FORCERENEW");
951
952         return 0;
953 }
954
955 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
956                              size_t len) {
957         _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
958         int r;
959
960         r = dhcp_lease_new(&lease);
961         if (r < 0)
962                 return r;
963
964         r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
965         if (r == DHCP_NAK) {
966                 log_dhcp_client(client, "NAK");
967                 return -EADDRNOTAVAIL;
968         }
969
970         if (r != DHCP_ACK) {
971                 log_dhcp_client(client, "receieved message was not an ACK, ignoring");
972                 return -ENOMSG;
973         }
974
975         lease->next_server = ack->siaddr;
976
977         lease->address = ack->yiaddr;
978
979         if (lease->address == INADDR_ANY ||
980             lease->server_address == INADDR_ANY ||
981             lease->lifetime == 0) {
982                 log_dhcp_client(client, "receieved lease lacks address, server "
983                                 "address or lease lifetime, ignoring");
984                 return -ENOMSG;
985         }
986
987         if (lease->subnet_mask == INADDR_ANY) {
988                 r = dhcp_lease_set_default_subnet_mask(lease);
989                 if (r < 0) {
990                         log_dhcp_client(client, "receieved lease lacks subnet "
991                                         "mask, and a fallback one can not be "
992                                         "generated, ignoring");
993                         return -ENOMSG;
994                 }
995         }
996
997         r = DHCP_EVENT_IP_ACQUIRE;
998         if (client->lease) {
999                 if (client->lease->address != lease->address ||
1000                     client->lease->subnet_mask != lease->subnet_mask ||
1001                     client->lease->router != lease->router) {
1002                         r = DHCP_EVENT_IP_CHANGE;
1003                 } else
1004                         r = DHCP_EVENT_RENEW;
1005
1006                 client->lease = sd_dhcp_lease_unref(client->lease);
1007         }
1008
1009         client->lease = lease;
1010         lease = NULL;
1011
1012         log_dhcp_client(client, "ACK");
1013
1014         return r;
1015 }
1016
1017 static uint64_t client_compute_timeout(sd_dhcp_client *client,
1018                                        uint32_t lifetime, double factor) {
1019         assert(client);
1020         assert(client->request_sent);
1021         assert(lifetime);
1022
1023         return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
1024                 + (random_u32() & 0x1fffff);
1025 }
1026
1027 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1028         usec_t time_now;
1029         uint64_t lifetime_timeout;
1030         uint64_t t2_timeout;
1031         uint64_t t1_timeout;
1032         char time_string[FORMAT_TIMESPAN_MAX];
1033         int r;
1034
1035         assert(client);
1036         assert(client->event);
1037         assert(client->lease);
1038         assert(client->lease->lifetime);
1039
1040         client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1041         client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1042         client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1043
1044         /* don't set timers for infinite leases */
1045         if (client->lease->lifetime == 0xffffffff)
1046                 return 0;
1047
1048         r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1049         if (r < 0)
1050                 return r;
1051         assert(client->request_sent <= time_now);
1052
1053         /* convert the various timeouts from relative (secs) to absolute (usecs) */
1054         lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1055         if (client->lease->t1 && client->lease->t2) {
1056                 /* both T1 and T2 are given */
1057                 if (client->lease->t1 < client->lease->t2 &&
1058                     client->lease->t2 < client->lease->lifetime) {
1059                         /* they are both valid */
1060                         t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1061                         t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1062                 } else {
1063                         /* discard both */
1064                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1065                         client->lease->t2 = (client->lease->lifetime * 7) / 8;
1066                         t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1067                         client->lease->t1 = client->lease->lifetime / 2;
1068                 }
1069         } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
1070                 /* only T2 is given, and it is valid */
1071                 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1072                 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1073                 client->lease->t1 = client->lease->lifetime / 2;
1074                 if (t2_timeout <= t1_timeout) {
1075                         /* the computed T1 would be invalid, so discard T2 */
1076                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1077                         client->lease->t2 = (client->lease->lifetime * 7) / 8;
1078                 }
1079         } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
1080                 /* only T1 is given, and it is valid */
1081                 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1082                 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1083                 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1084                 if (t2_timeout <= t1_timeout) {
1085                         /* the computed T2 would be invalid, so discard T1 */
1086                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1087                         client->lease->t2 = client->lease->lifetime / 2;
1088                 }
1089         } else {
1090                 /* fall back to the default timeouts */
1091                 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1092                 client->lease->t1 = client->lease->lifetime / 2;
1093                 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1094                 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1095         }
1096
1097         /* arm lifetime timeout */
1098         r = sd_event_add_time(client->event, &client->timeout_expire,
1099                               clock_boottime_or_monotonic(),
1100                               lifetime_timeout, 10 * USEC_PER_MSEC,
1101                               client_timeout_expire, client);
1102         if (r < 0)
1103                 return r;
1104
1105         r = sd_event_source_set_priority(client->timeout_expire,
1106                                          client->event_priority);
1107         if (r < 0)
1108                 return r;
1109
1110         log_dhcp_client(client, "lease expires in %s",
1111                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1112                         lifetime_timeout - time_now, 0));
1113
1114         /* don't arm earlier timeouts if this has already expired */
1115         if (lifetime_timeout <= time_now)
1116                 return 0;
1117
1118         /* arm T2 timeout */
1119         r = sd_event_add_time(client->event,
1120                               &client->timeout_t2,
1121                               clock_boottime_or_monotonic(),
1122                               t2_timeout,
1123                               10 * USEC_PER_MSEC,
1124                               client_timeout_t2, client);
1125         if (r < 0)
1126                 return r;
1127
1128         r = sd_event_source_set_priority(client->timeout_t2,
1129                                          client->event_priority);
1130         if (r < 0)
1131                 return r;
1132
1133         log_dhcp_client(client, "T2 expires in %s",
1134                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1135                         t2_timeout - time_now, 0));
1136
1137         /* don't arm earlier timeout if this has already expired */
1138         if (t2_timeout <= time_now)
1139                 return 0;
1140
1141         /* arm T1 timeout */
1142         r = sd_event_add_time(client->event,
1143                               &client->timeout_t1,
1144                               clock_boottime_or_monotonic(),
1145                               t1_timeout, 10 * USEC_PER_MSEC,
1146                               client_timeout_t1, client);
1147         if (r < 0)
1148                 return r;
1149
1150         r = sd_event_source_set_priority(client->timeout_t1,
1151                                          client->event_priority);
1152         if (r < 0)
1153                 return r;
1154
1155         log_dhcp_client(client, "T1 expires in %s",
1156                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1157                         t1_timeout - time_now, 0));
1158
1159         return 0;
1160 }
1161
1162 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1163                                  int len) {
1164         DHCP_CLIENT_DONT_DESTROY(client);
1165         int r = 0, notify_event = 0;
1166
1167         assert(client);
1168         assert(client->event);
1169         assert(message);
1170
1171         switch (client->state) {
1172         case DHCP_STATE_SELECTING:
1173
1174                 r = client_handle_offer(client, message, len);
1175                 if (r >= 0) {
1176
1177                         client->timeout_resend =
1178                                 sd_event_source_unref(client->timeout_resend);
1179
1180                         client->state = DHCP_STATE_REQUESTING;
1181                         client->attempt = 1;
1182
1183                         r = sd_event_add_time(client->event,
1184                                               &client->timeout_resend,
1185                                               clock_boottime_or_monotonic(),
1186                                               0, 0,
1187                                               client_timeout_resend, client);
1188                         if (r < 0)
1189                                 goto error;
1190
1191                         r = sd_event_source_set_priority(client->timeout_resend,
1192                                                          client->event_priority);
1193                         if (r < 0)
1194                                 goto error;
1195                 } else if (r == -ENOMSG)
1196                         /* invalid message, let's ignore it */
1197                         return 0;
1198
1199                 break;
1200
1201         case DHCP_STATE_REBOOTING:
1202         case DHCP_STATE_REQUESTING:
1203         case DHCP_STATE_RENEWING:
1204         case DHCP_STATE_REBINDING:
1205
1206                 r = client_handle_ack(client, message, len);
1207                 if (r >= 0) {
1208                         client->timeout_resend =
1209                                 sd_event_source_unref(client->timeout_resend);
1210
1211                         if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1212                                    DHCP_STATE_REBOOTING))
1213                                 notify_event = DHCP_EVENT_IP_ACQUIRE;
1214                         else if (r != DHCP_EVENT_IP_ACQUIRE)
1215                                 notify_event = r;
1216
1217                         client->state = DHCP_STATE_BOUND;
1218                         client->attempt = 1;
1219
1220                         client->last_addr = client->lease->address;
1221
1222                         r = client_set_lease_timeouts(client);
1223                         if (r < 0)
1224                                 goto error;
1225
1226                         r = dhcp_network_bind_udp_socket(client->lease->address,
1227                                                          DHCP_PORT_CLIENT);
1228                         if (r < 0) {
1229                                 log_dhcp_client(client, "could not bind UDP socket");
1230                                 goto error;
1231                         }
1232
1233                         client->fd = r;
1234
1235                         client_initialize_io_events(client, client_receive_message_udp);
1236
1237                         if (notify_event) {
1238                                 client_notify(client, notify_event);
1239                                 if (client->state == DHCP_STATE_STOPPED)
1240                                         return 0;
1241                         }
1242
1243                 } else if (r == -EADDRNOTAVAIL) {
1244                         /* got a NAK, let's restart the client */
1245                         client->timeout_resend =
1246                                 sd_event_source_unref(client->timeout_resend);
1247
1248                         r = client_initialize(client);
1249                         if (r < 0)
1250                                 goto error;
1251
1252                         r = client_start(client);
1253                         if (r < 0)
1254                                 goto error;
1255
1256                         log_dhcp_client(client, "REBOOTED");
1257
1258                         return 0;
1259                 } else if (r == -ENOMSG)
1260                         /* invalid message, let's ignore it */
1261                         return 0;
1262
1263                 break;
1264
1265         case DHCP_STATE_BOUND:
1266                 r = client_handle_forcerenew(client, message, len);
1267                 if (r >= 0) {
1268                         r = client_timeout_t1(NULL, 0, client);
1269                         if (r < 0)
1270                                 goto error;
1271                 } else if (r == -ENOMSG)
1272                         /* invalid message, let's ignore it */
1273                         return 0;
1274
1275                 break;
1276
1277         case DHCP_STATE_INIT:
1278         case DHCP_STATE_INIT_REBOOT:
1279
1280                 break;
1281
1282         case DHCP_STATE_STOPPED:
1283                 r = -EINVAL;
1284                 goto error;
1285         }
1286
1287 error:
1288         if (r < 0)
1289                 client_stop(client, r);
1290
1291         return r;
1292 }
1293
1294 static int client_receive_message_udp(sd_event_source *s, int fd,
1295                                       uint32_t revents, void *userdata) {
1296         sd_dhcp_client *client = userdata;
1297         _cleanup_free_ DHCPMessage *message = NULL;
1298         int buflen = 0, len, r;
1299
1300         assert(s);
1301         assert(client);
1302
1303         r = ioctl(fd, FIONREAD, &buflen);
1304         if (r < 0)
1305                 return r;
1306
1307         if (buflen < 0)
1308                 /* this can't be right */
1309                 return -EIO;
1310
1311         message = malloc0(buflen);
1312         if (!message)
1313                 return -ENOMEM;
1314
1315         len = read(fd, message, buflen);
1316         if (len < 0) {
1317                 log_dhcp_client(client, "could not receive message from UDP "
1318                                 "socket: %m");
1319                 return 0;
1320         } else if ((size_t)len < sizeof(DHCPMessage)) {
1321                 log_dhcp_client(client, "too small to be a DHCP message: ignoring");
1322                 return 0;
1323         }
1324
1325         if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1326                 log_dhcp_client(client, "not a DHCP message: ignoring");
1327                 return 0;
1328         }
1329
1330         if (message->op != BOOTREPLY) {
1331                 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1332                 return 0;
1333         }
1334
1335         if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
1336                 log_dhcp_client(client, "not an ethernet packet");
1337                 return 0;
1338         }
1339
1340         if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
1341                    ETH_ALEN)) {
1342                 log_dhcp_client(client, "received chaddr does not match "
1343                                 "expected: ignoring");
1344                 return 0;
1345         }
1346
1347         if (client->state != DHCP_STATE_BOUND &&
1348             be32toh(message->xid) != client->xid) {
1349                 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1350                    so ignore the xid in this case */
1351                 log_dhcp_client(client, "received xid (%u) does not match "
1352                                 "expected (%u): ignoring",
1353                                 be32toh(message->xid), client->xid);
1354                 return 0;
1355         }
1356
1357         return client_handle_message(client, message, len);
1358 }
1359
1360 static int client_receive_message_raw(sd_event_source *s, int fd,
1361                                       uint32_t revents, void *userdata) {
1362         sd_dhcp_client *client = userdata;
1363         _cleanup_free_ DHCPPacket *packet = NULL;
1364         uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1365         struct iovec iov = {};
1366         struct msghdr msg = {
1367                 .msg_iov = &iov,
1368                 .msg_iovlen = 1,
1369                 .msg_control = cmsgbuf,
1370                 .msg_controllen = sizeof(cmsgbuf),
1371         };
1372         struct cmsghdr *cmsg;
1373         bool checksum = true;
1374         int buflen = 0, len, r;
1375
1376         assert(s);
1377         assert(client);
1378
1379         r = ioctl(fd, FIONREAD, &buflen);
1380         if (r < 0)
1381                 return r;
1382
1383         if (buflen < 0)
1384                 /* this can't be right */
1385                 return -EIO;
1386
1387         packet = malloc0(buflen);
1388         if (!packet)
1389                 return -ENOMEM;
1390
1391         iov.iov_base = packet;
1392         iov.iov_len = buflen;
1393
1394         len = recvmsg(fd, &msg, 0);
1395         if (len < 0) {
1396                 log_dhcp_client(client, "could not receive message from raw "
1397                                 "socket: %m");
1398                 return 0;
1399         } else if ((size_t)len < sizeof(DHCPPacket))
1400                 return 0;
1401
1402         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1403                 if (cmsg->cmsg_level == SOL_PACKET &&
1404                     cmsg->cmsg_type == PACKET_AUXDATA &&
1405                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1406                         struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1407
1408                         checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1409                         break;
1410                 }
1411         }
1412
1413         r = dhcp_packet_verify_headers(packet, len, checksum);
1414         if (r < 0)
1415                 return 0;
1416
1417         len -= DHCP_IP_UDP_SIZE;
1418
1419         return client_handle_message(client, &packet->dhcp, len);
1420 }
1421
1422 int sd_dhcp_client_start(sd_dhcp_client *client) {
1423         int r;
1424
1425         assert_return(client, -EINVAL);
1426
1427         r = client_initialize(client);
1428         if (r < 0)
1429                 return r;
1430
1431         if (client->last_addr)
1432                 client->state = DHCP_STATE_INIT_REBOOT;
1433
1434         r = client_start(client);
1435         if (r >= 0)
1436                 log_dhcp_client(client, "STARTED on ifindex %u with address %s",
1437                                 client->index,
1438                                 ether_ntoa(&client->client_id.mac_addr));
1439
1440         return r;
1441 }
1442
1443 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1444         DHCP_CLIENT_DONT_DESTROY(client);
1445
1446         assert_return(client, -EINVAL);
1447
1448         client_stop(client, DHCP_EVENT_STOP);
1449         client->state = DHCP_STATE_STOPPED;
1450
1451         return 0;
1452 }
1453
1454 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1455                                 int priority) {
1456         int r;
1457
1458         assert_return(client, -EINVAL);
1459         assert_return(!client->event, -EBUSY);
1460
1461         if (event)
1462                 client->event = sd_event_ref(event);
1463         else {
1464                 r = sd_event_default(&client->event);
1465                 if (r < 0)
1466                         return 0;
1467         }
1468
1469         client->event_priority = priority;
1470
1471         return 0;
1472 }
1473
1474 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1475         assert_return(client, -EINVAL);
1476
1477         client->event = sd_event_unref(client->event);
1478
1479         return 0;
1480 }
1481
1482 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1483         if (!client)
1484                 return NULL;
1485
1486         return client->event;
1487 }
1488
1489 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1490         if (client)
1491                 assert_se(REFCNT_INC(client->n_ref) >= 2);
1492
1493         return client;
1494 }
1495
1496 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1497         if (client && REFCNT_DEC(client->n_ref) <= 0) {
1498                 log_dhcp_client(client, "FREE");
1499
1500                 client_initialize(client);
1501
1502                 client->receive_message =
1503                         sd_event_source_unref(client->receive_message);
1504
1505                 sd_dhcp_client_detach_event(client);
1506
1507                 sd_dhcp_lease_unref(client->lease);
1508
1509                 free(client->req_opts);
1510                 free(client->hostname);
1511                 free(client->vendor_class_identifier);
1512                 free(client);
1513         }
1514
1515         return NULL;
1516 }
1517
1518 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1519         _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
1520
1521         assert_return(ret, -EINVAL);
1522
1523         client = new0(sd_dhcp_client, 1);
1524         if (!client)
1525                 return -ENOMEM;
1526
1527         client->n_ref = REFCNT_INIT;
1528         client->state = DHCP_STATE_INIT;
1529         client->index = -1;
1530         client->fd = -1;
1531         client->attempt = 1;
1532         client->mtu = DHCP_DEFAULT_MIN_SIZE;
1533
1534         client->req_opts_size = ELEMENTSOF(default_req_opts);
1535
1536         client->req_opts = memdup(default_req_opts, client->req_opts_size);
1537         if (!client->req_opts)
1538                 return -ENOMEM;
1539
1540         *ret = client;
1541         client = NULL;
1542
1543         return 0;
1544 }