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 }