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