chiark / gitweb /
4be37a2389fef27912004f17a141df3c87ced973
[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 %d", 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         int r;
246
247         assert(client);
248         assert(client->secs);
249         assert(message);
250         assert(opt);
251         assert(optlen);
252
253         r = dhcp_message_init(message, BOOTREQUEST, client->xid, type, opt,
254                               optlen);
255         if (r < 0)
256                 return r;
257
258         /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
259            refuse to issue an DHCP lease if 'secs' is set to zero */
260         message->secs = htobe16(client->secs);
261
262         memcpy(&message->chaddr, &client->client_id.mac_addr, ETH_ALEN);
263
264         if (client->state == DHCP_STATE_RENEWING ||
265             client->state == DHCP_STATE_REBINDING)
266                 message->ciaddr = client->lease->address;
267
268         /* Some DHCP servers will refuse to issue an DHCP lease if the Client
269            Identifier option is not set */
270         r = dhcp_option_append(opt, optlen, DHCP_OPTION_CLIENT_IDENTIFIER,
271                                sizeof(client->client_id), &client->client_id);
272         if (r < 0)
273                 return r;
274
275         if (type == DHCP_DISCOVER || type == DHCP_REQUEST) {
276                 be16_t max_size;
277
278                 r = dhcp_option_append(opt, optlen,
279                                        DHCP_OPTION_PARAMETER_REQUEST_LIST,
280                                        client->req_opts_size,
281                                        client->req_opts);
282                 if (r < 0)
283                         return r;
284
285                 /* Some DHCP servers will send bigger DHCP packets than the
286                    defined default size unless the Maximum Messge Size option
287                    is explicitely set */
288                 max_size = htobe16(DHCP_IP_UDP_SIZE + DHCP_MESSAGE_SIZE +
289                                    DHCP_MIN_OPTIONS_SIZE);
290                 r = dhcp_option_append(opt, optlen,
291                                        DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
292                                        2, &max_size);
293                 if (r < 0)
294                         return r;
295         }
296
297         return 0;
298 }
299
300 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
301                                 size_t len) {
302         dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
303                                       INADDR_BROADCAST, DHCP_PORT_SERVER, len);
304
305         return dhcp_network_send_raw_socket(client->fd, &client->link,
306                                             packet, len);
307 }
308
309 static int client_send_discover(sd_dhcp_client *client) {
310         _cleanup_free_ DHCPPacket *discover = NULL;
311         size_t optlen, len;
312         uint8_t *opt;
313         usec_t time_now;
314         int r;
315
316         assert(client);
317
318         r = sd_event_now(client->event, CLOCK_MONOTONIC, &time_now);
319         if (r < 0)
320                 return r;
321         assert(time_now >= client->start_time);
322
323         /* seconds between sending first and last DISCOVER
324          * must always be strictly positive to deal with broken servers */
325         client->secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
326
327         optlen = DHCP_MIN_OPTIONS_SIZE;
328         len = sizeof(DHCPPacket) + optlen;
329
330         discover = malloc0(len);
331         if (!discover)
332                 return -ENOMEM;
333
334         r = client_message_init(client, &discover->dhcp, DHCP_DISCOVER,
335                                 &opt, &optlen);
336         if (r < 0)
337                 return r;
338
339         if (client->last_addr != INADDR_ANY) {
340                 r = dhcp_option_append(&opt, &optlen,
341                                          DHCP_OPTION_REQUESTED_IP_ADDRESS,
342                                          4, &client->last_addr);
343                 if (r < 0)
344                         return r;
345         }
346
347         r = dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
348         if (r < 0)
349                 return r;
350
351         r = dhcp_client_send_raw(client, discover, len - optlen);
352         if (r < 0)
353                 return r;
354
355         log_dhcp_client(client, "DISCOVER");
356
357         return 0;
358 }
359
360 static int client_send_request(sd_dhcp_client *client) {
361         _cleanup_free_ DHCPPacket *request;
362         size_t optlen, len;
363         uint8_t *opt;
364         int r;
365
366         optlen = DHCP_MIN_OPTIONS_SIZE;
367         len = sizeof(DHCPPacket) + optlen;
368
369         request = malloc0(len);
370         if (!request)
371                 return -ENOMEM;
372
373         r = client_message_init(client, &request->dhcp, DHCP_REQUEST, &opt,
374                                 &optlen);
375         if (r < 0)
376                 return r;
377
378         switch (client->state) {
379
380         case DHCP_STATE_INIT_REBOOT:
381                 r = dhcp_option_append(&opt, &optlen,
382                                          DHCP_OPTION_REQUESTED_IP_ADDRESS,
383                                          4, &client->last_addr);
384                 if (r < 0)
385                         return r;
386                 break;
387
388         case DHCP_STATE_REQUESTING:
389                 r = dhcp_option_append(&opt, &optlen,
390                                        DHCP_OPTION_REQUESTED_IP_ADDRESS,
391                                        4, &client->lease->address);
392                 if (r < 0)
393                         return r;
394
395                 r = dhcp_option_append(&opt, &optlen,
396                                        DHCP_OPTION_SERVER_IDENTIFIER,
397                                        4, &client->lease->server_address);
398                 if (r < 0)
399                         return r;
400                 break;
401
402         case DHCP_STATE_INIT:
403         case DHCP_STATE_SELECTING:
404         case DHCP_STATE_REBOOTING:
405         case DHCP_STATE_BOUND:
406         case DHCP_STATE_RENEWING:
407         case DHCP_STATE_REBINDING:
408
409                 break;
410
411         case DHCP_STATE_STOPPED:
412                 return -EINVAL;
413         }
414
415         r = dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
416         if (r < 0)
417                 return r;
418
419         if (client->state == DHCP_STATE_RENEWING) {
420                 r = dhcp_network_send_udp_socket(client->fd,
421                                                  client->lease->server_address,
422                                                  DHCP_PORT_SERVER,
423                                                  &request->dhcp,
424                                                  len - optlen - DHCP_IP_UDP_SIZE);
425         } else {
426                 r = dhcp_client_send_raw(client, request, len - optlen);
427         }
428         if (r < 0)
429                 return r;
430
431         log_dhcp_client(client, "REQUEST");
432
433         return 0;
434 }
435
436 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
437                                  void *userdata) {
438         sd_dhcp_client *client = userdata;
439         usec_t next_timeout = 0;
440         uint64_t time_now;
441         uint32_t time_left;
442         int r;
443
444         assert(s);
445         assert(client);
446         assert(client->event);
447
448         r = sd_event_now(client->event, CLOCK_MONOTONIC, &time_now);
449         if (r < 0)
450                 goto error;
451
452         switch (client->state) {
453         case DHCP_STATE_RENEWING:
454
455                 time_left = (client->lease->t2 - client->lease->t1) / 2;
456                 if (time_left < 60)
457                         time_left = 60;
458
459                 next_timeout = time_now + time_left * USEC_PER_SEC;
460
461                 break;
462
463         case DHCP_STATE_REBINDING:
464
465                 time_left = (client->lease->lifetime - client->lease->t2) / 2;
466                 if (time_left < 60)
467                         time_left = 60;
468
469                 next_timeout = time_now + time_left * USEC_PER_SEC;
470                 break;
471
472         case DHCP_STATE_REBOOTING:
473                 /* start over as we did not receive a timely ack or nak */
474                 client->state = DHCP_STATE_INIT;
475                 client->attempt = 1;
476
477                 client->fd = safe_close(client->fd);
478                 client->xid = random_u32();
479                 r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid);
480                 if (r < 0)
481                         goto error;
482                 client->fd = r;
483
484                 /* fall through */
485         case DHCP_STATE_INIT:
486         case DHCP_STATE_INIT_REBOOT:
487         case DHCP_STATE_SELECTING:
488         case DHCP_STATE_REQUESTING:
489         case DHCP_STATE_BOUND:
490
491                 if (client->attempt < 64)
492                         client->attempt *= 2;
493
494                 next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
495
496                 break;
497
498         case DHCP_STATE_STOPPED:
499                 r = -EINVAL;
500                 goto error;
501         }
502
503         next_timeout += (random_u32() & 0x1fffff);
504
505         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
506
507         r = sd_event_add_time(client->event,
508                               &client->timeout_resend,
509                               CLOCK_MONOTONIC,
510                               next_timeout, 10 * USEC_PER_MSEC,
511                               client_timeout_resend, client);
512         if (r < 0)
513                 goto error;
514
515         r = sd_event_source_set_priority(client->timeout_resend,
516                                          client->event_priority);
517         if (r < 0)
518                 goto error;
519
520         switch (client->state) {
521         case DHCP_STATE_INIT:
522                 r = client_send_discover(client);
523                 if (r >= 0) {
524                         client->state = DHCP_STATE_SELECTING;
525                         client->attempt = 1;
526                 } else {
527                         if (client->attempt >= 64)
528                                 goto error;
529                 }
530
531                 break;
532
533         case DHCP_STATE_SELECTING:
534                 r = client_send_discover(client);
535                 if (r < 0 && client->attempt >= 64)
536                         goto error;
537
538                 break;
539
540         case DHCP_STATE_INIT_REBOOT:
541         case DHCP_STATE_REQUESTING:
542         case DHCP_STATE_RENEWING:
543         case DHCP_STATE_REBINDING:
544                 r = client_send_request(client);
545                 if (r < 0 && client->attempt >= 64)
546                          goto error;
547
548                 if (client->state == DHCP_STATE_INIT_REBOOT)
549                         client->state = DHCP_STATE_REBOOTING;
550
551                 client->request_sent = time_now;
552
553                 break;
554
555         case DHCP_STATE_REBOOTING:
556         case DHCP_STATE_BOUND:
557
558                 break;
559
560         case DHCP_STATE_STOPPED:
561                 r = -EINVAL;
562                 goto error;
563         }
564
565         return 0;
566
567 error:
568         client_stop(client, r);
569
570         /* Errors were dealt with when stopping the client, don't spill
571            errors into the event loop handler */
572         return 0;
573 }
574
575 static int client_initialize_events(sd_dhcp_client *client,
576                                     sd_event_io_handler_t io_callback) {
577         int r;
578
579         assert(client);
580         assert(client->event);
581
582         r = sd_event_add_io(client->event, &client->receive_message,
583                             client->fd, EPOLLIN, io_callback,
584                             client);
585         if (r < 0)
586                 goto error;
587
588         r = sd_event_source_set_priority(client->receive_message,
589                                          client->event_priority);
590         if (r < 0)
591                 goto error;
592
593         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
594
595         r = sd_event_add_time(client->event,
596                               &client->timeout_resend,
597                               CLOCK_MONOTONIC,
598                               0, 0,
599                               client_timeout_resend, client);
600         if (r < 0)
601                 goto error;
602
603         r = sd_event_source_set_priority(client->timeout_resend,
604                                          client->event_priority);
605
606 error:
607         if (r < 0)
608                 client_stop(client, r);
609
610         return 0;
611
612 }
613
614 static int client_start(sd_dhcp_client *client) {
615         int r;
616
617         assert_return(client, -EINVAL);
618         assert_return(client->event, -EINVAL);
619         assert_return(client->index > 0, -EINVAL);
620         assert_return(client->fd < 0, -EBUSY);
621         assert_return(client->xid == 0, -EINVAL);
622         assert_return(client->state == DHCP_STATE_INIT ||
623                       client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
624
625         client->xid = random_u32();
626
627         r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid);
628
629         if (r < 0) {
630                 client_stop(client, r);
631                 return r;
632         }
633         client->fd = r;
634
635         if (client->state == DHCP_STATE_INIT) {
636                 client->start_time = now(CLOCK_MONOTONIC);
637                 client->secs = 0;
638         }
639
640         log_dhcp_client(client, "STARTED");
641
642         return client_initialize_events(client, client_receive_message_raw);
643 }
644
645 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
646                                  void *userdata) {
647         sd_dhcp_client *client = userdata;
648
649         log_dhcp_client(client, "EXPIRED");
650
651         client = client_notify(client, DHCP_EVENT_EXPIRED);
652
653         /* lease was lost, start over if not freed or stopped in callback */
654         if (client && client->state != DHCP_STATE_STOPPED) {
655                 client_initialize(client);
656                 client_start(client);
657         }
658
659         return 0;
660 }
661
662 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
663         sd_dhcp_client *client = userdata;
664         int r;
665
666         client->receive_message = sd_event_source_unref(client->receive_message);
667         client->fd = safe_close(client->fd);
668
669         client->state = DHCP_STATE_REBINDING;
670         client->attempt = 1;
671
672         r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid);
673         if (r < 0) {
674                 client_stop(client, r);
675                 return 0;
676         }
677
678         client->fd = r;
679
680         log_dhcp_client(client, "TIMEOUT T2");
681
682         return client_initialize_events(client, client_receive_message_raw);
683 }
684
685 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
686                              void *userdata) {
687         sd_dhcp_client *client = userdata;
688         int r;
689
690         client->state = DHCP_STATE_RENEWING;
691         client->attempt = 1;
692
693         r = dhcp_network_bind_udp_socket(client->index,
694                                          client->lease->address,
695                                          DHCP_PORT_CLIENT);
696         if (r < 0) {
697                 client_stop(client, r);
698                 return 0;
699         }
700
701         client->fd = r;
702
703         log_dhcp_client(client, "TIMEOUT T1");
704
705         return client_initialize_events(client, client_receive_message_udp);
706 }
707
708 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
709                                size_t len) {
710         _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
711         int r;
712
713         r = dhcp_lease_new(&lease);
714         if (r < 0)
715                 return r;
716
717         r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
718         if (r != DHCP_OFFER) {
719                 log_dhcp_client(client, "receieved message was not an OFFER, ignoring");
720                 return -ENOMSG;
721         }
722
723         lease->next_server = offer->siaddr;
724
725         lease->address = offer->yiaddr;
726
727         if (lease->address == INADDR_ANY ||
728             lease->server_address == INADDR_ANY ||
729             lease->lifetime == 0) {
730                 log_dhcp_client(client, "receieved lease lacks address, server "
731                                 "address or lease lifetime, ignoring");
732                 return -ENOMSG;
733         }
734
735         if (lease->subnet_mask == INADDR_ANY) {
736                 r = dhcp_lease_set_default_subnet_mask(lease);
737                 if (r < 0) {
738                         log_dhcp_client(client, "receieved lease lacks subnet "
739                                         "mask, and a fallback one can not be "
740                                         "generated, ignoring");
741                         return -ENOMSG;
742                 }
743         }
744
745         client->lease = lease;
746         lease = NULL;
747
748         log_dhcp_client(client, "OFFER");
749
750         return 0;
751 }
752
753 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
754                              size_t len) {
755         _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
756         int r;
757
758         r = dhcp_lease_new(&lease);
759         if (r < 0)
760                 return r;
761
762         r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
763         if (r == DHCP_NAK) {
764                 log_dhcp_client(client, "NAK");
765                 return DHCP_EVENT_NO_LEASE;
766         }
767
768         if (r != DHCP_ACK) {
769                 log_dhcp_client(client, "receieved message was not an ACK, ignoring");
770                 return -ENOMSG;
771         }
772
773         lease->next_server = ack->siaddr;
774
775         lease->address = ack->yiaddr;
776
777         if (lease->address == INADDR_ANY ||
778             lease->server_address == INADDR_ANY ||
779             lease->lifetime == 0) {
780                 log_dhcp_client(client, "receieved lease lacks address, server "
781                                 "address or lease lifetime, ignoring");
782                 return -ENOMSG;
783         }
784
785         if (lease->subnet_mask == INADDR_ANY) {
786                 r = dhcp_lease_set_default_subnet_mask(lease);
787                 if (r < 0) {
788                         log_dhcp_client(client, "receieved lease lacks subnet "
789                                         "mask, and a fallback one can not be "
790                                         "generated, ignoring");
791                         return -ENOMSG;
792                 }
793         }
794
795         r = DHCP_EVENT_IP_ACQUIRE;
796         if (client->lease) {
797                 if (client->lease->address != lease->address ||
798                     client->lease->subnet_mask != lease->subnet_mask ||
799                     client->lease->router != lease->router) {
800                         r = DHCP_EVENT_IP_CHANGE;
801                 }
802
803                 client->lease = sd_dhcp_lease_unref(client->lease);
804         }
805
806         client->lease = lease;
807         lease = NULL;
808
809         log_dhcp_client(client, "ACK");
810
811         return r;
812 }
813
814 static uint64_t client_compute_timeout(sd_dhcp_client *client,
815                                        uint32_t lifetime, double factor) {
816         assert(client);
817         assert(client->request_sent);
818         assert(lifetime);
819
820         return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
821                 + (random_u32() & 0x1fffff);
822 }
823
824 static int client_set_lease_timeouts(sd_dhcp_client *client) {
825         usec_t time_now;
826         uint64_t lifetime_timeout;
827         uint64_t t2_timeout;
828         uint64_t t1_timeout;
829         char time_string[FORMAT_TIMESPAN_MAX];
830         int r;
831
832         assert(client);
833         assert(client->event);
834         assert(client->lease);
835         assert(client->lease->lifetime);
836
837         client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
838         client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
839         client->timeout_expire = sd_event_source_unref(client->timeout_expire);
840
841         /* don't set timers for infinite leases */
842         if (client->lease->lifetime == 0xffffffff)
843                 return 0;
844
845         r = sd_event_now(client->event, CLOCK_MONOTONIC, &time_now);
846         if (r < 0)
847                 return r;
848         assert(client->request_sent <= time_now);
849
850         /* convert the various timeouts from relative (secs) to absolute (usecs) */
851         lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
852         if (client->lease->t1 && client->lease->t2) {
853                 /* both T1 and T2 are given */
854                 if (client->lease->t1 < client->lease->t2 &&
855                     client->lease->t2 < client->lease->lifetime) {
856                         /* they are both valid */
857                         t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
858                         t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
859                 } else {
860                         /* discard both */
861                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
862                         client->lease->t2 = (client->lease->lifetime * 7) / 8;
863                         t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
864                         client->lease->t1 = client->lease->lifetime / 2;
865                 }
866         } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
867                 /* only T2 is given, and it is valid */
868                 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
869                 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
870                 client->lease->t1 = client->lease->lifetime / 2;
871                 if (t2_timeout <= t1_timeout) {
872                         /* the computed T1 would be invalid, so discard T2 */
873                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
874                         client->lease->t2 = (client->lease->lifetime * 7) / 8;
875                 }
876         } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
877                 /* only T1 is given, and it is valid */
878                 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
879                 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
880                 client->lease->t2 = (client->lease->lifetime * 7) / 8;
881                 if (t2_timeout <= t1_timeout) {
882                         /* the computed T2 would be invalid, so discard T1 */
883                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
884                         client->lease->t2 = client->lease->lifetime / 2;
885                 }
886         } else {
887                 /* fall back to the default timeouts */
888                 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
889                 client->lease->t1 = client->lease->lifetime / 2;
890                 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
891                 client->lease->t2 = (client->lease->lifetime * 7) / 8;
892         }
893
894         /* arm lifetime timeout */
895         r = sd_event_add_time(client->event, &client->timeout_expire,
896                               CLOCK_MONOTONIC,
897                               lifetime_timeout, 10 * USEC_PER_MSEC,
898                               client_timeout_expire, client);
899         if (r < 0)
900                 return r;
901
902         r = sd_event_source_set_priority(client->timeout_expire,
903                                          client->event_priority);
904         if (r < 0)
905                 return r;
906
907         log_dhcp_client(client, "lease expires in %s",
908                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
909                         lifetime_timeout - time_now, 0));
910
911         /* don't arm earlier timeouts if this has already expired */
912         if (lifetime_timeout <= time_now)
913                 return 0;
914
915         /* arm T2 timeout */
916         r = sd_event_add_time(client->event,
917                               &client->timeout_t2,
918                               CLOCK_MONOTONIC,
919                               t2_timeout,
920                               10 * USEC_PER_MSEC,
921                               client_timeout_t2, client);
922         if (r < 0)
923                 return r;
924
925         r = sd_event_source_set_priority(client->timeout_t2,
926                                          client->event_priority);
927         if (r < 0)
928                 return r;
929
930         log_dhcp_client(client, "T2 expires in %s",
931                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
932                         t2_timeout - time_now, 0));
933
934         /* don't arm earlier timeout if this has already expired */
935         if (t2_timeout <= time_now)
936                 return 0;
937
938         /* arm T1 timeout */
939         r = sd_event_add_time(client->event,
940                               &client->timeout_t1,
941                               CLOCK_MONOTONIC,
942                               t1_timeout, 10 * USEC_PER_MSEC,
943                               client_timeout_t1, client);
944         if (r < 0)
945                 return r;
946
947         r = sd_event_source_set_priority(client->timeout_t1,
948                                          client->event_priority);
949         if (r < 0)
950                 return r;
951
952         log_dhcp_client(client, "T1 expires in %s",
953                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
954                         t1_timeout - time_now, 0));
955
956         return 0;
957 }
958
959 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
960                                  int len) {
961         int r = 0, notify_event = 0;
962
963         assert(client);
964         assert(client->event);
965         assert(message);
966
967         if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
968                 log_dhcp_client(client, "not a DHCP message: ignoring");
969                 return 0;
970         }
971
972         if (message->op != BOOTREPLY) {
973                 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
974                 return 0;
975         }
976
977         if (be32toh(message->xid) != client->xid) {
978                 log_dhcp_client(client, "received xid (%u) does not match "
979                                 "expected (%u): ignoring",
980                                 be32toh(message->xid), client->xid);
981                 return 0;
982         }
983
984         if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
985                 log_dhcp_client(client, "not an ethernet packet");
986                 return 0;
987         }
988
989         if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
990                    ETH_ALEN)) {
991                 log_dhcp_client(client, "received chaddr does not match "
992                                 "expected: ignoring");
993                 return 0;
994         }
995
996         switch (client->state) {
997         case DHCP_STATE_SELECTING:
998
999                 r = client_handle_offer(client, message, len);
1000                 if (r >= 0) {
1001
1002                         client->timeout_resend =
1003                                 sd_event_source_unref(client->timeout_resend);
1004
1005                         client->state = DHCP_STATE_REQUESTING;
1006                         client->attempt = 1;
1007
1008                         r = sd_event_add_time(client->event,
1009                                               &client->timeout_resend,
1010                                               CLOCK_MONOTONIC,
1011                                               0, 0,
1012                                               client_timeout_resend, client);
1013                         if (r < 0)
1014                                 goto error;
1015
1016                         r = sd_event_source_set_priority(client->timeout_resend,
1017                                                          client->event_priority);
1018                         if (r < 0)
1019                                 goto error;
1020                 } else if (r == -ENOMSG)
1021                         /* invalid message, let's ignore it */
1022                         return 0;
1023
1024                 break;
1025
1026         case DHCP_STATE_REBOOTING:
1027         case DHCP_STATE_REQUESTING:
1028         case DHCP_STATE_RENEWING:
1029         case DHCP_STATE_REBINDING:
1030
1031                 r = client_handle_ack(client, message, len);
1032                 if (r == DHCP_EVENT_NO_LEASE) {
1033
1034                         client->timeout_resend =
1035                                 sd_event_source_unref(client->timeout_resend);
1036
1037                         if (client->state == DHCP_STATE_REBOOTING) {
1038                                 r = client_initialize(client);
1039                                 if (r < 0)
1040                                         goto error;
1041
1042                                 r = client_start(client);
1043                                 if (r < 0)
1044                                         goto error;
1045                         }
1046
1047                         goto error;
1048                 } else if (r >= 0) {
1049                         client->timeout_resend =
1050                                 sd_event_source_unref(client->timeout_resend);
1051
1052                         if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1053                                    DHCP_STATE_REBOOTING))
1054                                 notify_event = DHCP_EVENT_IP_ACQUIRE;
1055                         else if (r != DHCP_EVENT_IP_ACQUIRE)
1056                                 notify_event = r;
1057
1058                         client->state = DHCP_STATE_BOUND;
1059                         client->attempt = 1;
1060
1061                         client->last_addr = client->lease->address;
1062
1063                         r = client_set_lease_timeouts(client);
1064                         if (r < 0)
1065                                 goto error;
1066
1067                         if (notify_event) {
1068                                 client = client_notify(client, notify_event);
1069                                 if (!client ||
1070                                     client->state == DHCP_STATE_STOPPED)
1071                                         return 0;
1072                         }
1073
1074                         client->receive_message =
1075                                 sd_event_source_unref(client->receive_message);
1076                         client->fd = safe_close(client->fd);
1077                 } else if (r == -ENOMSG)
1078                         /* invalid message, let's ignore it */
1079                         return 0;
1080
1081                 break;
1082
1083         case DHCP_STATE_INIT:
1084         case DHCP_STATE_INIT_REBOOT:
1085         case DHCP_STATE_BOUND:
1086
1087                 break;
1088
1089         case DHCP_STATE_STOPPED:
1090                 r = -EINVAL;
1091                 goto error;
1092         }
1093
1094 error:
1095         if (r < 0 || r == DHCP_EVENT_NO_LEASE)
1096                 client_stop(client, r);
1097
1098         return r;
1099 }
1100
1101 static int client_receive_message_udp(sd_event_source *s, int fd,
1102                                       uint32_t revents, void *userdata) {
1103         sd_dhcp_client *client = userdata;
1104         _cleanup_free_ DHCPMessage *message = NULL;
1105         int buflen = 0, len, r;
1106
1107         assert(s);
1108         assert(client);
1109
1110         r = ioctl(fd, FIONREAD, &buflen);
1111         if (r < 0 || buflen <= 0)
1112                 buflen = sizeof(DHCPMessage) + DHCP_MIN_OPTIONS_SIZE;
1113
1114         message = malloc0(buflen);
1115         if (!message)
1116                 return -ENOMEM;
1117
1118         len = read(fd, message, buflen);
1119         if (len < 0) {
1120                 log_dhcp_client(client, "could not receive message from UDP "
1121                                 "socket: %s", strerror(errno));
1122                 return 0;
1123         } else if ((size_t)len < sizeof(DHCPMessage))
1124                 return 0;
1125
1126         return client_handle_message(client, message, len);
1127 }
1128
1129 static int client_receive_message_raw(sd_event_source *s, int fd,
1130                                       uint32_t revents, void *userdata) {
1131         sd_dhcp_client *client = userdata;
1132         _cleanup_free_ DHCPPacket *packet = NULL;
1133         uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1134         struct iovec iov = {};
1135         struct msghdr msg = {
1136                 .msg_iov = &iov,
1137                 .msg_iovlen = 1,
1138                 .msg_control = cmsgbuf,
1139                 .msg_controllen = sizeof(cmsgbuf),
1140         };
1141         struct cmsghdr *cmsg;
1142         bool checksum = true;
1143         int buflen = 0, len, r;
1144
1145         assert(s);
1146         assert(client);
1147
1148         r = ioctl(fd, FIONREAD, &buflen);
1149         if (r < 0 || buflen <= 0)
1150                 buflen = sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE;
1151
1152         packet = malloc0(buflen);
1153         if (!packet)
1154                 return -ENOMEM;
1155
1156         iov.iov_base = packet;
1157         iov.iov_len = buflen;
1158
1159         len = recvmsg(fd, &msg, 0);
1160         if (len < 0) {
1161                 log_dhcp_client(client, "could not receive message from raw "
1162                                 "socket: %s", strerror(errno));
1163                 return 0;
1164         } else if ((size_t)len < sizeof(DHCPPacket))
1165                 return 0;
1166
1167         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1168                 if (cmsg->cmsg_level == SOL_PACKET &&
1169                     cmsg->cmsg_type == PACKET_AUXDATA &&
1170                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1171                         struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1172
1173                         checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1174                         break;
1175                 }
1176         }
1177
1178         r = dhcp_packet_verify_headers(packet, len, checksum);
1179         if (r < 0)
1180                 return 0;
1181
1182         len -= DHCP_IP_UDP_SIZE;
1183
1184         return client_handle_message(client, &packet->dhcp, len);
1185 }
1186
1187 int sd_dhcp_client_start(sd_dhcp_client *client) {
1188         int r;
1189
1190         assert_return(client, -EINVAL);
1191
1192         r = client_initialize(client);
1193         if (r < 0)
1194                 return r;
1195
1196         if (client->last_addr)
1197                 client->state = DHCP_STATE_INIT_REBOOT;
1198
1199         return client_start(client);
1200 }
1201
1202 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1203         assert_return(client, -EINVAL);
1204
1205         if (client_stop(client, DHCP_EVENT_STOP))
1206                 client->state = DHCP_STATE_STOPPED;
1207
1208         return 0;
1209 }
1210
1211 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1212                                 int priority) {
1213         int r;
1214
1215         assert_return(client, -EINVAL);
1216         assert_return(!client->event, -EBUSY);
1217
1218         if (event)
1219                 client->event = sd_event_ref(event);
1220         else {
1221                 r = sd_event_default(&client->event);
1222                 if (r < 0)
1223                         return 0;
1224         }
1225
1226         client->event_priority = priority;
1227
1228         return 0;
1229 }
1230
1231 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1232         assert_return(client, -EINVAL);
1233
1234         client->event = sd_event_unref(client->event);
1235
1236         return 0;
1237 }
1238
1239 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1240         if (!client)
1241                 return NULL;
1242
1243         return client->event;
1244 }
1245
1246 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1247         if (client)
1248                 assert_se(REFCNT_INC(client->n_ref) >= 2);
1249
1250         return client;
1251 }
1252
1253 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1254         if (client && REFCNT_DEC(client->n_ref) <= 0) {
1255                 log_dhcp_client(client, "UNREF");
1256
1257                 client_initialize(client);
1258
1259                 client->receive_message =
1260                         sd_event_source_unref(client->receive_message);
1261
1262                 sd_dhcp_client_detach_event(client);
1263
1264                 free(client->req_opts);
1265                 free(client);
1266
1267                 return NULL;
1268         }
1269
1270         return client;
1271 }
1272
1273 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_client*, sd_dhcp_client_unref);
1274 #define _cleanup_dhcp_client_free_ _cleanup_(sd_dhcp_client_unrefp)
1275
1276 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1277         _cleanup_dhcp_client_free_ sd_dhcp_client *client = NULL;
1278
1279         assert_return(ret, -EINVAL);
1280
1281         client = new0(sd_dhcp_client, 1);
1282         if (!client)
1283                 return -ENOMEM;
1284
1285         client->n_ref = REFCNT_INIT;
1286         client->state = DHCP_STATE_INIT;
1287         client->index = -1;
1288         client->fd = -1;
1289         client->attempt = 1;
1290
1291         client->req_opts_size = ELEMENTSOF(default_req_opts);
1292
1293         client->req_opts = memdup(default_req_opts, client->req_opts_size);
1294         if (!client->req_opts)
1295                 return -ENOMEM;
1296
1297         *ret = client;
1298         client = NULL;
1299
1300         return 0;
1301 }