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