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