chiark / gitweb /
sd-dhcp-client: refactor DNS support
[elogind.git] / src / libsystemd / 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 <sys/param.h>
26
27 #include "util.h"
28 #include "list.h"
29
30 #include "dhcp-protocol.h"
31 #include "dhcp-internal.h"
32 #include "sd-dhcp-client.h"
33
34 #define DHCP_CLIENT_MIN_OPTIONS_SIZE            312
35
36 struct DHCPLease {
37         uint32_t t1;
38         uint32_t t2;
39         uint32_t lifetime;
40         be32_t address;
41         be32_t server_address;
42         be32_t subnet_mask;
43         be32_t router;
44         struct in_addr *dns;
45         size_t dns_size;
46         uint16_t mtu;
47         char *hostname;
48 };
49
50 typedef struct DHCPLease DHCPLease;
51
52 struct sd_dhcp_client {
53         DHCPState state;
54         sd_event *event;
55         sd_event_source *timeout_resend;
56         int index;
57         int fd;
58         union sockaddr_union link;
59         sd_event_source *receive_message;
60         uint8_t *req_opts;
61         size_t req_opts_allocated;
62         size_t req_opts_size;
63         be32_t last_addr;
64         struct ether_addr mac_addr;
65         uint32_t xid;
66         usec_t start_time;
67         unsigned int attempt;
68         usec_t request_sent;
69         sd_event_source *timeout_t1;
70         sd_event_source *timeout_t2;
71         sd_event_source *timeout_expire;
72         sd_dhcp_client_cb_t cb;
73         void *userdata;
74         DHCPLease *lease;
75 };
76
77 static const uint8_t default_req_opts[] = {
78         DHCP_OPTION_SUBNET_MASK,
79         DHCP_OPTION_ROUTER,
80         DHCP_OPTION_HOST_NAME,
81         DHCP_OPTION_DOMAIN_NAME,
82         DHCP_OPTION_DOMAIN_NAME_SERVER,
83         DHCP_OPTION_NTP_SERVER,
84 };
85
86 static int client_receive_message(sd_event_source *s, int fd,
87                                   uint32_t revents, void *userdata);
88
89 int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
90                                 void *userdata)
91 {
92         assert_return(client, -EINVAL);
93
94         client->cb = cb;
95         client->userdata = userdata;
96
97         return 0;
98 }
99
100 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option)
101 {
102         size_t i;
103
104         assert_return(client, -EINVAL);
105         assert_return (client->state == DHCP_STATE_INIT, -EBUSY);
106
107         switch(option) {
108         case DHCP_OPTION_PAD:
109         case DHCP_OPTION_OVERLOAD:
110         case DHCP_OPTION_MESSAGE_TYPE:
111         case DHCP_OPTION_PARAMETER_REQUEST_LIST:
112         case DHCP_OPTION_END:
113                 return -EINVAL;
114
115         default:
116                 break;
117         }
118
119         for (i = 0; i < client->req_opts_size; i++)
120                 if (client->req_opts[i] == option)
121                         return -EEXIST;
122
123         if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
124                             client->req_opts_size + 1))
125                 return -ENOMEM;
126
127         client->req_opts[client->req_opts_size++] = option;
128
129         return 0;
130 }
131
132 int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
133                                        const struct in_addr *last_addr)
134 {
135         assert_return(client, -EINVAL);
136         assert_return(client->state == DHCP_STATE_INIT, -EBUSY);
137
138         if (last_addr)
139                 client->last_addr = last_addr->s_addr;
140         else
141                 client->last_addr = INADDR_ANY;
142
143         return 0;
144 }
145
146 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index)
147 {
148         assert_return(client, -EINVAL);
149         assert_return(client->state == DHCP_STATE_INIT, -EBUSY);
150         assert_return(interface_index >= -1, -EINVAL);
151
152         client->index = interface_index;
153
154         return 0;
155 }
156
157 int sd_dhcp_client_set_mac(sd_dhcp_client *client,
158                            const struct ether_addr *addr)
159 {
160         assert_return(client, -EINVAL);
161         assert_return(client->state == DHCP_STATE_INIT, -EBUSY);
162
163         memcpy(&client->mac_addr, addr, ETH_ALEN);
164
165         return 0;
166 }
167
168 int sd_dhcp_client_get_address(sd_dhcp_client *client, struct in_addr *addr)
169 {
170         assert_return(client, -EINVAL);
171         assert_return(addr, -EINVAL);
172
173         switch (client->state) {
174         case DHCP_STATE_INIT:
175         case DHCP_STATE_SELECTING:
176         case DHCP_STATE_INIT_REBOOT:
177         case DHCP_STATE_REBOOTING:
178         case DHCP_STATE_REQUESTING:
179                 return -EADDRNOTAVAIL;
180
181         case DHCP_STATE_BOUND:
182         case DHCP_STATE_RENEWING:
183         case DHCP_STATE_REBINDING:
184                 addr->s_addr = client->lease->address;
185
186                 break;
187         }
188
189         return 0;
190 }
191
192 int sd_dhcp_client_get_mtu(sd_dhcp_client *client, uint16_t *mtu)
193 {
194         assert_return(client, -EINVAL);
195         assert_return(mtu, -EINVAL);
196
197         switch (client->state) {
198         case DHCP_STATE_INIT:
199         case DHCP_STATE_SELECTING:
200         case DHCP_STATE_INIT_REBOOT:
201         case DHCP_STATE_REBOOTING:
202         case DHCP_STATE_REQUESTING:
203                 return -EADDRNOTAVAIL;
204
205         case DHCP_STATE_BOUND:
206         case DHCP_STATE_RENEWING:
207         case DHCP_STATE_REBINDING:
208                 if (client->lease->mtu)
209                         *mtu = client->lease->mtu;
210                 else
211                         return -ENOENT;
212
213                 break;
214         }
215
216         return 0;
217 }
218
219 int sd_dhcp_client_get_dns(sd_dhcp_client *client, struct in_addr **addr, size_t *addr_size)
220 {
221         assert_return(client, -EINVAL);
222         assert_return(addr, -EINVAL);
223         assert_return(addr_size, -EINVAL);
224
225         switch (client->state) {
226         case DHCP_STATE_INIT:
227         case DHCP_STATE_SELECTING:
228         case DHCP_STATE_INIT_REBOOT:
229         case DHCP_STATE_REBOOTING:
230         case DHCP_STATE_REQUESTING:
231                 return -EADDRNOTAVAIL;
232
233         case DHCP_STATE_BOUND:
234         case DHCP_STATE_RENEWING:
235         case DHCP_STATE_REBINDING:
236                 if (client->lease->dns_size) {
237                         *addr_size = client->lease->dns_size;
238                         *addr = client->lease->dns;
239                 } else
240                         return -ENOENT;
241
242                 break;
243         }
244
245         return 0;
246 }
247
248 int sd_dhcp_client_get_hostname(sd_dhcp_client *client, const char **hostname)
249 {
250         assert_return(client, -EINVAL);
251         assert_return(hostname, -EINVAL);
252
253         switch (client->state) {
254         case DHCP_STATE_INIT:
255         case DHCP_STATE_SELECTING:
256         case DHCP_STATE_INIT_REBOOT:
257         case DHCP_STATE_REBOOTING:
258         case DHCP_STATE_REQUESTING:
259                 return -EADDRNOTAVAIL;
260
261         case DHCP_STATE_BOUND:
262         case DHCP_STATE_RENEWING:
263         case DHCP_STATE_REBINDING:
264                 if (client->lease->hostname)
265                         *hostname = client->lease->hostname;
266                 else
267                         return -ENOENT;
268
269                 break;
270         }
271
272         return 0;
273 }
274
275 int sd_dhcp_client_prefixlen(const struct in_addr *addr)
276 {
277         int len = 0;
278         uint32_t mask;
279
280         assert_return(addr, -EADDRNOTAVAIL);
281
282         mask = be32toh(addr->s_addr);
283         while (mask) {
284                 len++;
285                 mask = mask << 1;
286         }
287
288         return len;
289 }
290
291 int sd_dhcp_client_get_router(sd_dhcp_client *client, struct in_addr *addr)
292 {
293         assert_return(client, -EINVAL);
294         assert_return(addr, -EINVAL);
295
296         switch (client->state) {
297         case DHCP_STATE_INIT:
298         case DHCP_STATE_SELECTING:
299         case DHCP_STATE_INIT_REBOOT:
300         case DHCP_STATE_REBOOTING:
301         case DHCP_STATE_REQUESTING:
302                 return -EADDRNOTAVAIL;
303
304         case DHCP_STATE_BOUND:
305         case DHCP_STATE_RENEWING:
306         case DHCP_STATE_REBINDING:
307                 addr->s_addr = client->lease->router;
308
309                 break;
310         }
311
312         return 0;
313 }
314
315 int sd_dhcp_client_get_netmask(sd_dhcp_client *client, struct in_addr *addr)
316 {
317         assert_return(client, -EINVAL);
318         assert_return(addr, -EINVAL);
319
320         switch (client->state) {
321         case DHCP_STATE_INIT:
322         case DHCP_STATE_SELECTING:
323         case DHCP_STATE_INIT_REBOOT:
324         case DHCP_STATE_REBOOTING:
325         case DHCP_STATE_REQUESTING:
326                 return -EADDRNOTAVAIL;
327
328         case DHCP_STATE_BOUND:
329         case DHCP_STATE_RENEWING:
330         case DHCP_STATE_REBINDING:
331                 addr->s_addr = client->lease->subnet_mask;
332
333                 break;
334         }
335
336         return 0;
337 }
338
339 static int client_notify(sd_dhcp_client *client, int event)
340 {
341         if (client->cb)
342                 client->cb(client, event, client->userdata);
343
344         return 0;
345 }
346
347 static int client_stop(sd_dhcp_client *client, int error)
348 {
349         assert_return(client, -EINVAL);
350
351         client->receive_message =
352                 sd_event_source_unref(client->receive_message);
353
354         if (client->fd >= 0)
355                 close(client->fd);
356         client->fd = -1;
357
358         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
359
360         client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
361         client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
362         client->timeout_expire = sd_event_source_unref(client->timeout_expire);
363
364         client->attempt = 1;
365
366         client_notify(client, error);
367
368         switch (client->state) {
369
370         case DHCP_STATE_INIT:
371         case DHCP_STATE_SELECTING:
372         case DHCP_STATE_REQUESTING:
373         case DHCP_STATE_BOUND:
374
375                 client->start_time = 0;
376                 client->state = DHCP_STATE_INIT;
377                 break;
378
379         case DHCP_STATE_INIT_REBOOT:
380         case DHCP_STATE_REBOOTING:
381         case DHCP_STATE_RENEWING:
382         case DHCP_STATE_REBINDING:
383
384                 break;
385         }
386
387         if (client->lease) {
388                 free(client->lease->dns);
389                 free(client->lease);
390                 client->lease = NULL;
391         }
392
393         return 0;
394 }
395
396 static int client_packet_init(sd_dhcp_client *client, uint8_t type,
397                               DHCPMessage *message, uint16_t secs,
398                               uint8_t **opt, size_t *optlen)
399 {
400         int err;
401         be16_t max_size;
402
403         *opt = (uint8_t *)(message + 1);
404
405         if (*optlen < 4)
406                 return -ENOBUFS;
407         *optlen -= 4;
408
409         message->op = BOOTREQUEST;
410         message->htype = 1;
411         message->hlen = ETHER_ADDR_LEN;
412         message->xid = htobe32(client->xid);
413
414         /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
415            refuse to issue an DHCP lease if 'secs' is set to zero */
416         message->secs = htobe16(secs);
417
418         if (client->state == DHCP_STATE_RENEWING ||
419             client->state == DHCP_STATE_REBINDING)
420                 message->ciaddr = client->lease->address;
421
422         memcpy(&message->chaddr, &client->mac_addr, ETH_ALEN);
423         (*opt)[0] = 0x63;
424         (*opt)[1] = 0x82;
425         (*opt)[2] = 0x53;
426         (*opt)[3] = 0x63;
427
428         *opt += 4;
429
430         err = dhcp_option_append(opt, optlen, DHCP_OPTION_MESSAGE_TYPE, 1,
431                                  &type);
432         if (err < 0)
433                 return err;
434
435         /* Some DHCP servers will refuse to issue an DHCP lease if the Cliient
436            Identifier option is not set */
437         err = dhcp_option_append(opt, optlen, DHCP_OPTION_CLIENT_IDENTIFIER,
438                                  ETH_ALEN, &client->mac_addr);
439         if (err < 0)
440                 return err;
441
442         if (type == DHCP_DISCOVER || type == DHCP_REQUEST) {
443                 err = dhcp_option_append(opt, optlen,
444                                          DHCP_OPTION_PARAMETER_REQUEST_LIST,
445                                          client->req_opts_size,
446                                          client->req_opts);
447                 if (err < 0)
448                         return err;
449
450                 /* Some DHCP servers will send bigger DHCP packets than the
451                    defined default size unless the Maximum Messge Size option
452                    is explicitely set */
453                 max_size = htobe16(DHCP_IP_UDP_SIZE + DHCP_MESSAGE_SIZE +
454                                    DHCP_CLIENT_MIN_OPTIONS_SIZE);
455                 err = dhcp_option_append(opt, optlen,
456                                          DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
457                                          2, &max_size);
458                 if (err < 0)
459                         return err;
460         }
461
462         return 0;
463 }
464
465 static uint16_t client_checksum(void *buf, int len)
466 {
467         uint32_t sum;
468         uint16_t *check;
469         int i;
470         uint8_t *odd;
471
472         sum = 0;
473         check = buf;
474
475         for (i = 0; i < len / 2 ; i++)
476                 sum += check[i];
477
478         if (len & 0x01) {
479                 odd = buf;
480                 sum += odd[len - 1];
481         }
482
483         while (sum >> 16)
484                 sum = (sum & 0xffff) + (sum >> 16);
485
486         return ~sum;
487 }
488
489 static void client_append_ip_headers(DHCPPacket *packet, uint16_t len)
490 {
491         packet->ip.version = IPVERSION;
492         packet->ip.ihl = DHCP_IP_SIZE / 4;
493         packet->ip.tot_len = htobe16(len);
494
495         packet->ip.protocol = IPPROTO_UDP;
496         packet->ip.saddr = INADDR_ANY;
497         packet->ip.daddr = INADDR_BROADCAST;
498
499         packet->udp.source = htobe16(DHCP_PORT_CLIENT);
500         packet->udp.dest = htobe16(DHCP_PORT_SERVER);
501         packet->udp.len = htobe16(len - DHCP_IP_SIZE);
502
503         packet->ip.check = packet->udp.len;
504         packet->udp.check = client_checksum(&packet->ip.ttl, len - 8);
505
506         packet->ip.ttl = IPDEFTTL;
507         packet->ip.check = 0;
508         packet->ip.check = client_checksum(&packet->ip, DHCP_IP_SIZE);
509 }
510
511 static int client_send_discover(sd_dhcp_client *client, uint16_t secs)
512 {
513         int err = 0;
514         _cleanup_free_ DHCPPacket *discover;
515         size_t optlen, len;
516         uint8_t *opt;
517
518         optlen = DHCP_CLIENT_MIN_OPTIONS_SIZE;
519         len = sizeof(DHCPPacket) + optlen;
520
521         discover = malloc0(len);
522
523         if (!discover)
524                 return -ENOMEM;
525
526         err = client_packet_init(client, DHCP_DISCOVER, &discover->dhcp,
527                                  secs, &opt, &optlen);
528         if (err < 0)
529                 return err;
530
531         if (client->last_addr != INADDR_ANY) {
532                 err = dhcp_option_append(&opt, &optlen,
533                                          DHCP_OPTION_REQUESTED_IP_ADDRESS,
534                                          4, &client->last_addr);
535                 if (err < 0)
536                         return err;
537         }
538
539         err = dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
540         if (err < 0)
541                 return err;
542
543         client_append_ip_headers(discover, len);
544
545         err = dhcp_network_send_raw_socket(client->fd, &client->link,
546                                            discover, len);
547
548         return err;
549 }
550
551 static int client_send_request(sd_dhcp_client *client, uint16_t secs)
552 {
553         _cleanup_free_ DHCPPacket *request;
554         size_t optlen, len;
555         int err;
556         uint8_t *opt;
557
558         optlen = DHCP_CLIENT_MIN_OPTIONS_SIZE;
559         len = DHCP_MESSAGE_SIZE + optlen;
560
561         request = malloc0(len);
562         if (!request)
563                 return -ENOMEM;
564
565         err = client_packet_init(client, DHCP_REQUEST, &request->dhcp, secs,
566                                  &opt, &optlen);
567         if (err < 0)
568                 return err;
569
570         if (client->state == DHCP_STATE_REQUESTING) {
571                 err = dhcp_option_append(&opt, &optlen,
572                                          DHCP_OPTION_REQUESTED_IP_ADDRESS,
573                                          4, &client->lease->address);
574                 if (err < 0)
575                         return err;
576
577                 err = dhcp_option_append(&opt, &optlen,
578                                          DHCP_OPTION_SERVER_IDENTIFIER,
579                                          4, &client->lease->server_address);
580                 if (err < 0)
581                         return err;
582         }
583
584         err = dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
585         if (err < 0)
586                 return err;
587
588         if (client->state == DHCP_STATE_RENEWING) {
589                 err = dhcp_network_send_udp_socket(client->fd,
590                                                    client->lease->server_address,
591                                                    &request->dhcp,
592                                                    len - DHCP_IP_UDP_SIZE);
593         } else {
594                 client_append_ip_headers(request, len);
595
596                 err = dhcp_network_send_raw_socket(client->fd, &client->link,
597                                                    request, len);
598         }
599
600         return err;
601 }
602
603 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
604                                  void *userdata)
605 {
606         sd_dhcp_client *client = userdata;
607         usec_t next_timeout = 0;
608         uint32_t time_left;
609         uint16_t secs;
610         int err = 0;
611
612         switch (client->state) {
613         case DHCP_STATE_RENEWING:
614
615                 time_left = (client->lease->t2 - client->lease->t1)/2;
616                 if (time_left < 60)
617                         time_left = 60;
618
619                 next_timeout = usec + time_left * USEC_PER_SEC;
620
621                 break;
622
623         case DHCP_STATE_REBINDING:
624
625                 time_left = (client->lease->lifetime - client->lease->t2)/2;
626                 if (time_left < 60)
627                         time_left = 60;
628
629                 next_timeout = usec + time_left * USEC_PER_SEC;
630                 break;
631
632         case DHCP_STATE_INIT:
633         case DHCP_STATE_INIT_REBOOT:
634         case DHCP_STATE_REBOOTING:
635         case DHCP_STATE_SELECTING:
636         case DHCP_STATE_REQUESTING:
637         case DHCP_STATE_BOUND:
638
639                 if (client->attempt < 64)
640                         client->attempt *= 2;
641
642                 next_timeout = usec + (client->attempt - 1) * USEC_PER_SEC;
643
644                 break;
645         }
646
647         next_timeout += (random_u32() & 0x1fffff);
648
649         err = sd_event_add_monotonic(client->event, next_timeout,
650                                      10 * USEC_PER_MSEC,
651                                      client_timeout_resend, client,
652                                      &client->timeout_resend);
653         if (err < 0)
654                 goto error;
655
656         secs = (usec - client->start_time) / USEC_PER_SEC;
657
658         switch (client->state) {
659         case DHCP_STATE_INIT:
660                 err = client_send_discover(client, secs);
661                 if (err >= 0) {
662                         client->state = DHCP_STATE_SELECTING;
663                         client->attempt = 1;
664                 } else {
665                         if (client->attempt >= 64)
666                                 goto error;
667                 }
668
669                 break;
670
671         case DHCP_STATE_SELECTING:
672                 err = client_send_discover(client, secs);
673                 if (err < 0 && client->attempt >= 64)
674                         goto error;
675
676                 break;
677
678         case DHCP_STATE_REQUESTING:
679         case DHCP_STATE_RENEWING:
680         case DHCP_STATE_REBINDING:
681                 err = client_send_request(client, secs);
682                 if (err < 0 && client->attempt >= 64)
683                          goto error;
684
685                 client->request_sent = usec;
686
687                 break;
688
689         case DHCP_STATE_INIT_REBOOT:
690         case DHCP_STATE_REBOOTING:
691         case DHCP_STATE_BOUND:
692
693                 break;
694         }
695
696         return 0;
697
698 error:
699         client_stop(client, err);
700
701         /* Errors were dealt with when stopping the client, don't spill
702            errors into the event loop handler */
703         return 0;
704 }
705
706 static int client_initialize_events(sd_dhcp_client *client, usec_t usec)
707 {
708         int r;
709
710         r = sd_event_add_io(client->event, client->fd, EPOLLIN,
711                             client_receive_message, client,
712                             &client->receive_message);
713         if (r < 0)
714                 goto error;
715
716         r = sd_event_add_monotonic(client->event, usec, 0,
717                                    client_timeout_resend, client,
718                                    &client->timeout_resend);
719
720 error:
721         if (r < 0)
722                 client_stop(client, r);
723
724         return 0;
725
726 }
727
728 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
729                                  void *userdata)
730 {
731         sd_dhcp_client *client = userdata;
732
733         client_stop(client, DHCP_EVENT_EXPIRED);
734
735         return 0;
736 }
737
738 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
739 {
740         sd_dhcp_client *client = userdata;
741         int r;
742
743         if (client->fd >= 0) {
744                 client->receive_message =
745                         sd_event_source_unref(client->receive_message);
746                 close(client->fd);
747                 client->fd = -1;
748         }
749
750         client->state = DHCP_STATE_REBINDING;
751         client->attempt = 1;
752
753         r = dhcp_network_bind_raw_socket(client->index, &client->link);
754         if (r < 0) {
755                 client_stop(client, r);
756                 return 0;
757         }
758
759         client->fd = r;
760
761         return client_initialize_events(client, usec);
762 }
763
764 static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
765 {
766         sd_dhcp_client *client = userdata;
767         int r;
768
769         client->state = DHCP_STATE_RENEWING;
770         client->attempt = 1;
771
772         r = dhcp_network_bind_udp_socket(client->index,
773                                          client->lease->address);
774         if (r < 0) {
775                 client_stop(client, r);
776                 return 0;
777         }
778
779         client->fd = r;
780
781         return client_initialize_events(client, usec);
782 }
783
784 static int client_parse_offer(uint8_t code, uint8_t len, const uint8_t *option,
785                               void *user_data)
786 {
787         DHCPLease *lease = user_data;
788         be32_t val;
789
790         switch(code) {
791
792         case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
793                 if (len == 4) {
794                         memcpy(&val, option, 4);
795                         lease->lifetime = be32toh(val);
796                 }
797
798                 break;
799
800         case DHCP_OPTION_SERVER_IDENTIFIER:
801                 if (len >= 4)
802                         memcpy(&lease->server_address, option, 4);
803
804                 break;
805
806         case DHCP_OPTION_SUBNET_MASK:
807                 if (len >= 4)
808                         memcpy(&lease->subnet_mask, option, 4);
809
810                 break;
811
812         case DHCP_OPTION_ROUTER:
813                 if (len >= 4)
814                         memcpy(&lease->router, option, 4);
815
816                 break;
817
818         case DHCP_OPTION_DOMAIN_NAME_SERVER:
819                 if (len >= 4) {
820                         unsigned i;
821
822                         lease->dns_size = len / 4;
823
824                         free(lease->dns);
825                         lease->dns = new0(struct in_addr, lease->dns_size);
826                         if (!lease->dns)
827                                 return -ENOMEM;
828
829                         for (i = 0; i < lease->dns_size; i++) {
830                                 memcpy(&lease->dns[i].s_addr, option + 4 * i, 4);
831                         }
832                 }
833
834                 break;
835
836         case DHCP_OPTION_INTERFACE_MTU:
837                 if (len >= 2) {
838                         be16_t mtu;
839
840                         memcpy(&mtu, option, 2);
841                         lease->mtu = be16toh(mtu);
842
843                         if (lease->mtu < 68)
844                                 lease->mtu = 0;
845                 }
846
847                 break;
848
849         case DHCP_OPTION_HOST_NAME:
850                 if (len >= 1) {
851                         free(lease->hostname);
852                         lease->hostname = strndup((const char *)option, len);
853                 }
854
855                 break;
856
857         case DHCP_OPTION_RENEWAL_T1_TIME:
858                 if (len == 4) {
859                         memcpy(&val, option, 4);
860                         lease->t1 = be32toh(val);
861                 }
862
863                 break;
864
865         case DHCP_OPTION_REBINDING_T2_TIME:
866                 if (len == 4) {
867                         memcpy(&val, option, 4);
868                         lease->t2 = be32toh(val);
869                 }
870
871                 break;
872         }
873
874         return 0;
875 }
876
877 static int client_verify_headers(sd_dhcp_client *client, DHCPPacket *message,
878                                  size_t len)
879 {
880         size_t hdrlen;
881
882         if (len < (DHCP_IP_UDP_SIZE + DHCP_MESSAGE_SIZE))
883                 return -EINVAL;
884
885         hdrlen = message->ip.ihl * 4;
886         if (hdrlen < 20 || hdrlen > len || client_checksum(&message->ip,
887                                                            hdrlen))
888                 return -EINVAL;
889
890         message->ip.check = message->udp.len;
891         message->ip.ttl = 0;
892
893         if (hdrlen + be16toh(message->udp.len) > len ||
894             client_checksum(&message->ip.ttl, be16toh(message->udp.len) + 12))
895                 return -EINVAL;
896
897         if (be16toh(message->udp.source) != DHCP_PORT_SERVER ||
898             be16toh(message->udp.dest) != DHCP_PORT_CLIENT)
899                 return -EINVAL;
900
901         if (message->dhcp.op != BOOTREPLY)
902                 return -EINVAL;
903
904         if (be32toh(message->dhcp.xid) != client->xid)
905                 return -EINVAL;
906
907         if (memcmp(&message->dhcp.chaddr[0], &client->mac_addr.ether_addr_octet,
908                     ETHER_ADDR_LEN))
909                 return -EINVAL;
910
911         return 0;
912 }
913
914 static int client_receive_offer(sd_dhcp_client *client, DHCPPacket *offer,
915                                 size_t len)
916 {
917         int err;
918         DHCPLease *lease;
919
920         err = client_verify_headers(client, offer, len);
921         if (err < 0)
922                 return err;
923
924         lease = new0(DHCPLease, 1);
925         if (!lease)
926                 return -ENOMEM;
927
928         len = len - DHCP_IP_UDP_SIZE;
929         if (dhcp_option_parse(&offer->dhcp, len, client_parse_offer,
930                               lease) != DHCP_OFFER)
931                 goto error;
932
933         lease->address = offer->dhcp.yiaddr;
934
935         if (lease->address == INADDR_ANY ||
936             lease->server_address == INADDR_ANY ||
937             lease->subnet_mask == INADDR_ANY ||
938             lease->lifetime == 0)
939                 goto error;
940
941         client->lease = lease;
942
943         return 0;
944
945 error:
946         free(lease);
947
948         return -ENOMSG;
949 }
950
951 static int client_receive_ack(sd_dhcp_client *client, const uint8_t *buf,
952                               size_t len)
953 {
954         int r;
955         DHCPPacket *ack;
956         DHCPMessage *dhcp;
957         DHCPLease *lease;
958
959         if (client->state == DHCP_STATE_RENEWING) {
960                 dhcp = (DHCPMessage *)buf;
961         } else {
962                 ack = (DHCPPacket *)buf;
963
964                 r = client_verify_headers(client, ack, len);
965                 if (r < 0)
966                         return r;
967
968                 dhcp = &ack->dhcp;
969                 len -= DHCP_IP_UDP_SIZE;
970         }
971
972         lease = new0(DHCPLease, 1);
973         if (!lease)
974                 return -ENOMEM;
975
976         r = dhcp_option_parse(dhcp, len, client_parse_offer, lease);
977
978         if (r == DHCP_NAK) {
979                 r = DHCP_EVENT_NO_LEASE;
980                 goto error;
981         }
982
983         if (r != DHCP_ACK) {
984                 r = -ENOMSG;
985                 goto error;
986         }
987
988         lease->address = dhcp->yiaddr;
989
990         if (lease->address == INADDR_ANY ||
991             lease->server_address == INADDR_ANY ||
992             lease->subnet_mask == INADDR_ANY || lease->lifetime == 0) {
993                 r = -ENOMSG;
994                 goto error;
995         }
996
997         r = DHCP_EVENT_IP_ACQUIRE;
998         if (client->lease) {
999                 if (client->lease->address != lease->address ||
1000                     client->lease->subnet_mask != lease->subnet_mask ||
1001                     client->lease->router != lease->router) {
1002                         r = DHCP_EVENT_IP_CHANGE;
1003                 }
1004
1005                 free(client->lease);
1006         }
1007
1008         client->lease = lease;
1009
1010         return r;
1011
1012 error:
1013         free(lease);
1014
1015         return r;
1016 }
1017
1018 static uint64_t client_compute_timeout(uint64_t request_sent,
1019                                        uint32_t lifetime)
1020 {
1021         return request_sent + (lifetime - 3) * USEC_PER_SEC +
1022                 + (random_u32() & 0x1fffff);
1023 }
1024
1025 static int client_set_lease_timeouts(sd_dhcp_client *client, uint64_t usec)
1026 {
1027         int err;
1028         uint64_t next_timeout;
1029
1030         if (client->lease->lifetime < 10)
1031                 return -EINVAL;
1032
1033         client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1034         client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1035         client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1036
1037         if (!client->lease->t1)
1038                 client->lease->t1 = client->lease->lifetime / 2;
1039
1040         next_timeout = client_compute_timeout(client->request_sent,
1041                                               client->lease->t1);
1042         if (next_timeout < usec)
1043                 return -EINVAL;
1044
1045         err = sd_event_add_monotonic(client->event, next_timeout,
1046                                      10 * USEC_PER_MSEC,
1047                                      client_timeout_t1, client,
1048                                      &client->timeout_t1);
1049         if (err < 0)
1050                 return err;
1051
1052         if (!client->lease->t2)
1053                 client->lease->t2 = client->lease->lifetime * 7 / 8;
1054
1055         if (client->lease->t2 < client->lease->t1)
1056                 return -EINVAL;
1057
1058         if (client->lease->lifetime < client->lease->t2)
1059                 return -EINVAL;
1060
1061         next_timeout = client_compute_timeout(client->request_sent,
1062                                               client->lease->t2);
1063         if (next_timeout < usec)
1064                 return -EINVAL;
1065
1066         err = sd_event_add_monotonic(client->event, next_timeout,
1067                                      10 * USEC_PER_MSEC,
1068                                      client_timeout_t2, client,
1069                                      &client->timeout_t2);
1070         if (err < 0)
1071                 return err;
1072
1073         next_timeout = client_compute_timeout(client->request_sent,
1074                                               client->lease->lifetime);
1075         if (next_timeout < usec)
1076                 return -EINVAL;
1077
1078         err = sd_event_add_monotonic(client->event, next_timeout,
1079                                      10 * USEC_PER_MSEC,
1080                                      client_timeout_expire, client,
1081                                      &client->timeout_expire);
1082         if (err < 0)
1083                 return err;
1084
1085         return 0;
1086 }
1087
1088 static int client_receive_message(sd_event_source *s, int fd,
1089                                   uint32_t revents, void *userdata)
1090 {
1091         sd_dhcp_client *client = userdata;
1092         uint8_t buf[sizeof(DHCPPacket) + DHCP_CLIENT_MIN_OPTIONS_SIZE];
1093         int buflen = sizeof(buf);
1094         int len, r = 0, notify_event = 0;
1095         DHCPPacket *message;
1096         usec_t time_now;
1097
1098         len = read(fd, &buf, buflen);
1099         if (len < 0)
1100                 return 0;
1101
1102         r = sd_event_get_now_monotonic(client->event, &time_now);
1103         if (r < 0)
1104                 goto error;
1105
1106         switch (client->state) {
1107         case DHCP_STATE_SELECTING:
1108
1109                 message = (DHCPPacket *)&buf;
1110
1111                 if (client_receive_offer(client, message, len) >= 0) {
1112
1113                         client->timeout_resend =
1114                                 sd_event_source_unref(client->timeout_resend);
1115
1116                         client->state = DHCP_STATE_REQUESTING;
1117                         client->attempt = 1;
1118
1119                         r = sd_event_add_monotonic(client->event, time_now, 0,
1120                                                    client_timeout_resend,
1121                                                    client,
1122                                                    &client->timeout_resend);
1123                         if (r < 0)
1124                                 goto error;
1125                 }
1126
1127                 break;
1128
1129         case DHCP_STATE_REQUESTING:
1130         case DHCP_STATE_RENEWING:
1131         case DHCP_STATE_REBINDING:
1132
1133                 r = client_receive_ack(client, buf, len);
1134
1135                 if (r == DHCP_EVENT_NO_LEASE)
1136                         goto error;
1137
1138                 if (r >= 0) {
1139                         client->timeout_resend =
1140                                 sd_event_source_unref(client->timeout_resend);
1141
1142                         if (client->state == DHCP_STATE_REQUESTING)
1143                                 notify_event = DHCP_EVENT_IP_ACQUIRE;
1144                         else if (r != DHCP_EVENT_IP_ACQUIRE)
1145                                 notify_event = r;
1146
1147                         client->state = DHCP_STATE_BOUND;
1148                         client->attempt = 1;
1149
1150                         client->last_addr = client->lease->address;
1151
1152                         r = client_set_lease_timeouts(client, time_now);
1153                         if (r < 0)
1154                                 goto error;
1155
1156                         if (notify_event)
1157                                 client_notify(client, notify_event);
1158
1159                         client->receive_message =
1160                                 sd_event_source_unref(client->receive_message);
1161                         close(client->fd);
1162                         client->fd = -1;
1163                 }
1164
1165                 r = 0;
1166
1167                 break;
1168
1169         case DHCP_STATE_INIT:
1170         case DHCP_STATE_INIT_REBOOT:
1171         case DHCP_STATE_REBOOTING:
1172         case DHCP_STATE_BOUND:
1173
1174                 break;
1175         }
1176
1177 error:
1178         if (r < 0 || r == DHCP_EVENT_NO_LEASE)
1179                 return client_stop(client, r);
1180
1181         return 0;
1182 }
1183
1184 int sd_dhcp_client_start(sd_dhcp_client *client)
1185 {
1186         int r;
1187
1188         assert_return(client, -EINVAL);
1189         assert_return(client->index > 0, -EINVAL);
1190         assert_return(client->state == DHCP_STATE_INIT ||
1191                       client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
1192
1193         client->xid = random_u32();
1194
1195         r = dhcp_network_bind_raw_socket(client->index, &client->link);
1196
1197         if (r < 0) {
1198                 client_stop(client, r);
1199                 return r;
1200         }
1201
1202         client->fd = r;
1203         client->start_time = now(CLOCK_MONOTONIC);
1204
1205         return client_initialize_events(client, client->start_time);
1206 }
1207
1208 int sd_dhcp_client_stop(sd_dhcp_client *client)
1209 {
1210         return client_stop(client, DHCP_EVENT_STOP);
1211 }
1212
1213 sd_dhcp_client *sd_dhcp_client_free(sd_dhcp_client *client)
1214 {
1215         assert_return(client, NULL);
1216
1217         sd_dhcp_client_stop(client);
1218
1219         sd_event_unref(client->event);
1220         free(client->req_opts);
1221         free(client);
1222
1223         return NULL;
1224 }
1225
1226 sd_dhcp_client *sd_dhcp_client_new(sd_event *event)
1227 {
1228         sd_dhcp_client *client;
1229
1230         assert_return(event, NULL);
1231
1232         client = new0(sd_dhcp_client, 1);
1233         if (!client)
1234                 return NULL;
1235
1236         client->event = sd_event_ref(event);
1237         client->state = DHCP_STATE_INIT;
1238         client->index = -1;
1239         client->fd = -1;
1240         client->attempt = 1;
1241
1242         client->req_opts_size = ELEMENTSOF(default_req_opts);
1243
1244         client->req_opts = memdup(default_req_opts, client->req_opts_size);
1245         if (!client->req_opts) {
1246                 free(client);
1247                 return NULL;
1248         }
1249
1250         return client;
1251 }