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