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