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