chiark / gitweb /
man: bring systemd.network(5) up-to-date
[elogind.git] / src / libsystemd-network / 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 <net/if_arp.h>
26 #include <netinet/ether.h>
27 #include <sys/param.h>
28 #include <sys/ioctl.h>
29
30 #include "util.h"
31 #include "list.h"
32 #include "refcnt.h"
33 #include "async.h"
34
35 #include "dhcp-protocol.h"
36 #include "dhcp-internal.h"
37 #include "dhcp-lease-internal.h"
38 #include "sd-dhcp-client.h"
39
40 struct sd_dhcp_client {
41         RefCount n_ref;
42
43         DHCPState state;
44         sd_event *event;
45         int event_priority;
46         sd_event_source *timeout_resend;
47         int index;
48         int fd;
49         union sockaddr_union link;
50         sd_event_source *receive_message;
51         uint8_t *req_opts;
52         size_t req_opts_allocated;
53         size_t req_opts_size;
54         be32_t last_addr;
55         struct {
56                 uint8_t type;
57                 struct ether_addr mac_addr;
58         } _packed_ client_id;
59         uint32_t xid;
60         usec_t start_time;
61         uint16_t secs;
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         sd_dhcp_lease *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_raw(sd_event_source *s, int fd,
82                                       uint32_t revents, void *userdata);
83 static int client_receive_message_udp(sd_event_source *s, int fd,
84                                       uint32_t revents, void *userdata);
85 static void client_stop(sd_dhcp_client *client, int error);
86
87 int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
88                                 void *userdata) {
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         size_t i;
99
100         assert_return(client, -EINVAL);
101         assert_return (IN_SET(client->state, DHCP_STATE_INIT,
102                               DHCP_STATE_STOPPED), -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         assert_return(client, -EINVAL);
132         assert_return (IN_SET(client->state, DHCP_STATE_INIT,
133                               DHCP_STATE_STOPPED), -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         assert_return(client, -EINVAL);
145         assert_return (IN_SET(client->state, DHCP_STATE_INIT,
146                               DHCP_STATE_STOPPED), -EBUSY);
147         assert_return(interface_index > 0, -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         DHCP_CLIENT_DONT_DESTROY(client);
157         bool need_restart = false;
158
159         assert_return(client, -EINVAL);
160         assert_return(addr, -EINVAL);
161
162         if (memcmp(&client->client_id.mac_addr, addr, ETH_ALEN) == 0)
163                 return 0;
164
165         if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
166                 log_dhcp_client(client, "Changing MAC address on running DHCP "
167                                 "client, restarting");
168                 need_restart = true;
169                 client_stop(client, DHCP_EVENT_STOP);
170         }
171
172         memcpy(&client->client_id.mac_addr, addr, ETH_ALEN);
173         client->client_id.type = 0x01;
174
175         if (need_restart && client->state != DHCP_STATE_STOPPED)
176                 sd_dhcp_client_start(client);
177
178         return 0;
179 }
180
181 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
182         assert_return(client, -EINVAL);
183         assert_return(ret, -EINVAL);
184
185         if (client->state != DHCP_STATE_BOUND &&
186             client->state != DHCP_STATE_RENEWING &&
187             client->state != DHCP_STATE_REBINDING)
188                 return -EADDRNOTAVAIL;
189
190         *ret = sd_dhcp_lease_ref(client->lease);
191
192         return 0;
193 }
194
195 static void client_notify(sd_dhcp_client *client, int event) {
196         if (client->cb)
197                 client->cb(client, event, client->userdata);
198 }
199
200 static int client_initialize(sd_dhcp_client *client) {
201         assert_return(client, -EINVAL);
202
203         client->receive_message =
204                 sd_event_source_unref(client->receive_message);
205
206         client->fd = asynchronous_close(client->fd);
207
208         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
209
210         client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
211         client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
212         client->timeout_expire = sd_event_source_unref(client->timeout_expire);
213
214         client->attempt = 1;
215
216         client->state = DHCP_STATE_INIT;
217         client->xid = 0;
218
219         if (client->lease)
220                 client->lease = sd_dhcp_lease_unref(client->lease);
221
222         return 0;
223 }
224
225 static void client_stop(sd_dhcp_client *client, int error) {
226         assert(client);
227
228         if (error < 0)
229                 log_dhcp_client(client, "STOPPED: %s", strerror(-error));
230         else {
231                 switch(error) {
232                 case DHCP_EVENT_STOP:
233                         log_dhcp_client(client, "STOPPED");
234                         break;
235                 case DHCP_EVENT_NO_LEASE:
236                         log_dhcp_client(client, "STOPPED: No lease");
237                         break;
238                 default:
239                         log_dhcp_client(client, "STOPPED: Unknown reason");
240                         break;
241                 }
242         }
243
244         client_notify(client, error);
245
246         client_initialize(client);
247 }
248
249 static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
250                                uint8_t type, size_t *_optlen, size_t *_optoffset) {
251         _cleanup_free_ DHCPPacket *packet;
252         size_t optlen, optoffset, size;
253         be16_t max_size;
254         int r;
255
256         assert(client);
257         assert(client->secs);
258         assert(ret);
259         assert(_optlen);
260         assert(_optoffset);
261         assert(type == DHCP_DISCOVER || type == DHCP_REQUEST);
262
263         optlen = DHCP_MIN_OPTIONS_SIZE;
264         size = sizeof(DHCPPacket) + optlen;
265
266         packet = malloc0(size);
267         if (!packet)
268                 return -ENOMEM;
269
270         r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
271                               optlen, &optoffset);
272         if (r < 0)
273                 return r;
274
275         /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
276            refuse to issue an DHCP lease if 'secs' is set to zero */
277         packet->dhcp.secs = htobe16(client->secs);
278
279         /* RFC2132 section 4.1
280            A client that cannot receive unicast IP datagrams until its protocol
281            software has been configured with an IP address SHOULD set the
282            BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
283            DHCPREQUEST messages that client sends.  The BROADCAST bit will
284            provide a hint to the DHCP server and BOOTP relay agent to broadcast
285            any messages to the client on the client's subnet. */
286         packet->dhcp.flags = htobe16(0x8000);
287
288         /* RFC2132 section 4.1.1:
289            The client MUST include its hardware address in the ’chaddr’ field, if
290            necessary for delivery of DHCP reply messages.
291          */
292         memcpy(&packet->dhcp.chaddr, &client->client_id.mac_addr, ETH_ALEN);
293
294         /* Some DHCP servers will refuse to issue an DHCP lease if the Client
295            Identifier option is not set */
296         r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
297                                DHCP_OPTION_CLIENT_IDENTIFIER,
298                                sizeof(client->client_id), &client->client_id);
299         if (r < 0)
300                 return r;
301
302
303         /* RFC2131 section 3.5:
304            in its initial DHCPDISCOVER or DHCPREQUEST message, a
305            client may provide the server with a list of specific
306            parameters the client is interested in. If the client
307            includes a list of parameters in a DHCPDISCOVER message,
308            it MUST include that list in any subsequent DHCPREQUEST
309            messages.
310          */
311         r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
312                                DHCP_OPTION_PARAMETER_REQUEST_LIST,
313                                client->req_opts_size, client->req_opts);
314         if (r < 0)
315                 return r;
316
317         /* RFC2131 section 3.5:
318            The client SHOULD include the ’maximum DHCP message size’ option to
319            let the server know how large the server may make its DHCP messages.
320
321            Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
322            than the defined default size unless the Maximum Messge Size option
323            is explicitely set
324          */
325         max_size = htobe16(size);
326         r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
327                                DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
328                                2, &max_size);
329         if (r < 0)
330                 return r;
331
332         *_optlen = optlen;
333         *_optoffset = optoffset;
334         *ret = packet;
335         packet = NULL;
336
337         return 0;
338 }
339
340 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
341                                 size_t len) {
342         dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
343                                       INADDR_BROADCAST, DHCP_PORT_SERVER, len);
344
345         return dhcp_network_send_raw_socket(client->fd, &client->link,
346                                             packet, len);
347 }
348
349 static int client_send_discover(sd_dhcp_client *client) {
350         _cleanup_free_ DHCPPacket *discover = NULL;
351         size_t optoffset, optlen;
352         usec_t time_now;
353         int r;
354
355         assert(client);
356         assert(client->state == DHCP_STATE_INIT ||
357                client->state == DHCP_STATE_SELECTING);
358
359         /* See RFC2131 section 4.4.1 */
360
361         r = sd_event_now(client->event, CLOCK_MONOTONIC, &time_now);
362         if (r < 0)
363                 return r;
364         assert(time_now >= client->start_time);
365
366         /* seconds between sending first and last DISCOVER
367          * must always be strictly positive to deal with broken servers */
368         client->secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
369
370         r = client_message_init(client, &discover, DHCP_DISCOVER,
371                                 &optlen, &optoffset);
372         if (r < 0)
373                 return r;
374
375         /* the client may suggest values for the network address
376            and lease time in the DHCPDISCOVER message. The client may include
377            the ’requested IP address’ option to suggest that a particular IP
378            address be assigned, and may include the ’IP address lease time’
379            option to suggest the lease time it would like.
380          */
381         if (client->last_addr != INADDR_ANY) {
382                 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
383                                        DHCP_OPTION_REQUESTED_IP_ADDRESS,
384                                        4, &client->last_addr);
385                 if (r < 0)
386                         return r;
387         }
388
389         r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
390                                DHCP_OPTION_END, 0, NULL);
391         if (r < 0)
392                 return r;
393
394         /* We currently ignore:
395            The client SHOULD wait a random time between one and ten seconds to
396            desynchronize the use of DHCP at startup.
397          */
398         r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
399         if (r < 0)
400                 return r;
401
402         log_dhcp_client(client, "DISCOVER");
403
404         return 0;
405 }
406
407 static int client_send_request(sd_dhcp_client *client) {
408         _cleanup_free_ DHCPPacket *request = NULL;
409         size_t optoffset, optlen;
410         int r;
411
412         r = client_message_init(client, &request, DHCP_REQUEST,
413                                 &optlen, &optoffset);
414         if (r < 0)
415                 return r;
416
417         switch (client->state) {
418         /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
419            SELECTING should be REQUESTING)
420          */
421
422         case DHCP_STATE_REQUESTING:
423                 /* Client inserts the address of the selected server in ’server
424                    identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
425                    filled in with the yiaddr value from the chosen DHCPOFFER.
426                  */
427
428                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
429                                        DHCP_OPTION_SERVER_IDENTIFIER,
430                                        4, &client->lease->server_address);
431                 if (r < 0)
432                         return r;
433
434                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
435                                        DHCP_OPTION_REQUESTED_IP_ADDRESS,
436                                        4, &client->lease->address);
437                 if (r < 0)
438                         return r;
439
440                 break;
441
442         case DHCP_STATE_INIT_REBOOT:
443                 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
444                    option MUST be filled in with client’s notion of its previously
445                    assigned address. ’ciaddr’ MUST be zero.
446                  */
447                 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
448                                        DHCP_OPTION_REQUESTED_IP_ADDRESS,
449                                        4, &client->last_addr);
450                 if (r < 0)
451                         return r;
452                 break;
453
454         case DHCP_STATE_RENEWING:
455                 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
456                    option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
457                    client’s IP address.
458                 */
459
460                 /* fall through */
461         case DHCP_STATE_REBINDING:
462                 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
463                    option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
464                    client’s IP address.
465
466                    This message MUST be broadcast to the 0xffffffff IP broadcast address.
467                  */
468                 request->dhcp.ciaddr = client->lease->address;
469
470                 break;
471
472         case DHCP_STATE_INIT:
473         case DHCP_STATE_SELECTING:
474         case DHCP_STATE_REBOOTING:
475         case DHCP_STATE_BOUND:
476         case DHCP_STATE_STOPPED:
477                 return -EINVAL;
478         }
479
480         r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
481                                DHCP_OPTION_END, 0, NULL);
482         if (r < 0)
483                 return r;
484
485         if (client->state == DHCP_STATE_RENEWING) {
486                 r = dhcp_network_send_udp_socket(client->fd,
487                                                  client->lease->server_address,
488                                                  DHCP_PORT_SERVER,
489                                                  &request->dhcp,
490                                                  sizeof(DHCPMessage) + optoffset);
491         } else {
492                 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
493         }
494         if (r < 0)
495                 return r;
496
497         switch (client->state) {
498         case DHCP_STATE_REQUESTING:
499                 log_dhcp_client(client, "REQUEST (requesting)");
500                 break;
501         case DHCP_STATE_INIT_REBOOT:
502                 log_dhcp_client(client, "REQUEST (init-reboot)");
503                 break;
504         case DHCP_STATE_RENEWING:
505                 log_dhcp_client(client, "REQUEST (renewing)");
506                 break;
507         case DHCP_STATE_REBINDING:
508                 log_dhcp_client(client, "REQUEST (rebinding)");
509                 break;
510         default:
511                 log_dhcp_client(client, "REQUEST (invalid)");
512                 break;
513         }
514
515         return 0;
516 }
517
518 static int client_start(sd_dhcp_client *client);
519
520 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
521                                  void *userdata) {
522         sd_dhcp_client *client = userdata;
523         DHCP_CLIENT_DONT_DESTROY(client);
524         usec_t next_timeout = 0;
525         uint64_t time_now;
526         uint32_t time_left;
527         int r;
528
529         assert(s);
530         assert(client);
531         assert(client->event);
532
533         r = sd_event_now(client->event, CLOCK_MONOTONIC, &time_now);
534         if (r < 0)
535                 goto error;
536
537         switch (client->state) {
538         case DHCP_STATE_RENEWING:
539
540                 time_left = (client->lease->t2 - client->lease->t1) / 2;
541                 if (time_left < 60)
542                         time_left = 60;
543
544                 next_timeout = time_now + time_left * USEC_PER_SEC;
545
546                 break;
547
548         case DHCP_STATE_REBINDING:
549
550                 time_left = (client->lease->lifetime - client->lease->t2) / 2;
551                 if (time_left < 60)
552                         time_left = 60;
553
554                 next_timeout = time_now + time_left * USEC_PER_SEC;
555                 break;
556
557         case DHCP_STATE_REBOOTING:
558                 /* start over as we did not receive a timely ack or nak */
559                 r = client_initialize(client);
560                 if (r < 0)
561                         goto error;
562
563                 r = client_start(client);
564                 if (r < 0)
565                         goto error;
566                 else {
567                         log_dhcp_client(client, "REBOOTED");
568                         return 0;
569                 }
570
571         case DHCP_STATE_INIT:
572         case DHCP_STATE_INIT_REBOOT:
573         case DHCP_STATE_SELECTING:
574         case DHCP_STATE_REQUESTING:
575         case DHCP_STATE_BOUND:
576
577                 if (client->attempt < 64)
578                         client->attempt *= 2;
579
580                 next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
581
582                 break;
583
584         case DHCP_STATE_STOPPED:
585                 r = -EINVAL;
586                 goto error;
587         }
588
589         next_timeout += (random_u32() & 0x1fffff);
590
591         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
592
593         r = sd_event_add_time(client->event,
594                               &client->timeout_resend,
595                               CLOCK_MONOTONIC,
596                               next_timeout, 10 * USEC_PER_MSEC,
597                               client_timeout_resend, client);
598         if (r < 0)
599                 goto error;
600
601         r = sd_event_source_set_priority(client->timeout_resend,
602                                          client->event_priority);
603         if (r < 0)
604                 goto error;
605
606         switch (client->state) {
607         case DHCP_STATE_INIT:
608                 r = client_send_discover(client);
609                 if (r >= 0) {
610                         client->state = DHCP_STATE_SELECTING;
611                         client->attempt = 1;
612                 } else {
613                         if (client->attempt >= 64)
614                                 goto error;
615                 }
616
617                 break;
618
619         case DHCP_STATE_SELECTING:
620                 r = client_send_discover(client);
621                 if (r < 0 && client->attempt >= 64)
622                         goto error;
623
624                 break;
625
626         case DHCP_STATE_INIT_REBOOT:
627         case DHCP_STATE_REQUESTING:
628         case DHCP_STATE_RENEWING:
629         case DHCP_STATE_REBINDING:
630                 r = client_send_request(client);
631                 if (r < 0 && client->attempt >= 64)
632                          goto error;
633
634                 if (client->state == DHCP_STATE_INIT_REBOOT)
635                         client->state = DHCP_STATE_REBOOTING;
636
637                 client->request_sent = time_now;
638
639                 break;
640
641         case DHCP_STATE_REBOOTING:
642         case DHCP_STATE_BOUND:
643
644                 break;
645
646         case DHCP_STATE_STOPPED:
647                 r = -EINVAL;
648                 goto error;
649         }
650
651         return 0;
652
653 error:
654         client_stop(client, r);
655
656         /* Errors were dealt with when stopping the client, don't spill
657            errors into the event loop handler */
658         return 0;
659 }
660
661 static int client_initialize_events(sd_dhcp_client *client,
662                                     sd_event_io_handler_t io_callback) {
663         int r;
664
665         assert(client);
666         assert(client->event);
667
668         r = sd_event_add_io(client->event, &client->receive_message,
669                             client->fd, EPOLLIN, io_callback,
670                             client);
671         if (r < 0)
672                 goto error;
673
674         r = sd_event_source_set_priority(client->receive_message,
675                                          client->event_priority);
676         if (r < 0)
677                 goto error;
678
679         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
680
681         r = sd_event_add_time(client->event,
682                               &client->timeout_resend,
683                               CLOCK_MONOTONIC,
684                               0, 0,
685                               client_timeout_resend, client);
686         if (r < 0)
687                 goto error;
688
689         r = sd_event_source_set_priority(client->timeout_resend,
690                                          client->event_priority);
691
692 error:
693         if (r < 0)
694                 client_stop(client, r);
695
696         return 0;
697
698 }
699
700 static int client_start(sd_dhcp_client *client) {
701         int r;
702
703         assert_return(client, -EINVAL);
704         assert_return(client->event, -EINVAL);
705         assert_return(client->index > 0, -EINVAL);
706         assert_return(client->fd < 0, -EBUSY);
707         assert_return(client->xid == 0, -EINVAL);
708         assert_return(client->state == DHCP_STATE_INIT ||
709                       client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
710
711         client->xid = random_u32();
712
713         r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid);
714         if (r < 0) {
715                 client_stop(client, r);
716                 return r;
717         }
718         client->fd = r;
719
720         if (client->state == DHCP_STATE_INIT) {
721                 client->start_time = now(CLOCK_MONOTONIC);
722                 client->secs = 0;
723         }
724
725         return client_initialize_events(client, client_receive_message_raw);
726 }
727
728 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
729                                  void *userdata) {
730         sd_dhcp_client *client = userdata;
731         DHCP_CLIENT_DONT_DESTROY(client);
732
733         log_dhcp_client(client, "EXPIRED");
734
735         client_notify(client, DHCP_EVENT_EXPIRED);
736
737         /* lease was lost, start over if not freed or stopped in callback */
738         if (client->state != DHCP_STATE_STOPPED) {
739                 client_initialize(client);
740                 client_start(client);
741         }
742
743         return 0;
744 }
745
746 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
747         sd_dhcp_client *client = userdata;
748         DHCP_CLIENT_DONT_DESTROY(client);
749         int r;
750
751         client->receive_message = sd_event_source_unref(client->receive_message);
752         client->fd = asynchronous_close(client->fd);
753
754         client->state = DHCP_STATE_REBINDING;
755         client->attempt = 1;
756
757         r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid);
758         if (r < 0) {
759                 client_stop(client, r);
760                 return 0;
761         }
762         client->fd = r;
763
764         return client_initialize_events(client, client_receive_message_raw);
765 }
766
767 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
768                              void *userdata) {
769         sd_dhcp_client *client = userdata;
770         DHCP_CLIENT_DONT_DESTROY(client);
771         int r;
772
773         client->state = DHCP_STATE_RENEWING;
774         client->attempt = 1;
775
776         r = dhcp_network_bind_udp_socket(client->lease->address,
777                                          DHCP_PORT_CLIENT);
778         if (r < 0) {
779                 log_dhcp_client(client, "could not bind UDP socket");
780                 return 0;
781         }
782
783         client->fd = r;
784
785         return client_initialize_events(client, client_receive_message_udp);
786 }
787
788 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
789                                size_t len) {
790         _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
791         int r;
792
793         r = dhcp_lease_new(&lease);
794         if (r < 0)
795                 return r;
796
797         r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
798         if (r != DHCP_OFFER) {
799                 log_dhcp_client(client, "receieved message was not an OFFER, ignoring");
800                 return -ENOMSG;
801         }
802
803         lease->next_server = offer->siaddr;
804
805         lease->address = offer->yiaddr;
806
807         if (lease->address == INADDR_ANY ||
808             lease->server_address == INADDR_ANY ||
809             lease->lifetime == 0) {
810                 log_dhcp_client(client, "receieved lease lacks address, server "
811                                 "address or lease lifetime, ignoring");
812                 return -ENOMSG;
813         }
814
815         if (lease->subnet_mask == INADDR_ANY) {
816                 r = dhcp_lease_set_default_subnet_mask(lease);
817                 if (r < 0) {
818                         log_dhcp_client(client, "receieved lease lacks subnet "
819                                         "mask, and a fallback one can not be "
820                                         "generated, ignoring");
821                         return -ENOMSG;
822                 }
823         }
824
825         sd_dhcp_lease_unref(client->lease);
826         client->lease = lease;
827         lease = NULL;
828
829         log_dhcp_client(client, "OFFER");
830
831         return 0;
832 }
833
834 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
835                              size_t len) {
836         _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
837         int r;
838
839         r = dhcp_lease_new(&lease);
840         if (r < 0)
841                 return r;
842
843         r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
844         if (r == DHCP_NAK) {
845                 log_dhcp_client(client, "NAK");
846                 return DHCP_EVENT_NO_LEASE;
847         }
848
849         if (r != DHCP_ACK) {
850                 log_dhcp_client(client, "receieved message was not an ACK, ignoring");
851                 return -ENOMSG;
852         }
853
854         lease->next_server = ack->siaddr;
855
856         lease->address = ack->yiaddr;
857
858         if (lease->address == INADDR_ANY ||
859             lease->server_address == INADDR_ANY ||
860             lease->lifetime == 0) {
861                 log_dhcp_client(client, "receieved lease lacks address, server "
862                                 "address or lease lifetime, ignoring");
863                 return -ENOMSG;
864         }
865
866         if (lease->subnet_mask == INADDR_ANY) {
867                 r = dhcp_lease_set_default_subnet_mask(lease);
868                 if (r < 0) {
869                         log_dhcp_client(client, "receieved lease lacks subnet "
870                                         "mask, and a fallback one can not be "
871                                         "generated, ignoring");
872                         return -ENOMSG;
873                 }
874         }
875
876         r = DHCP_EVENT_IP_ACQUIRE;
877         if (client->lease) {
878                 if (client->lease->address != lease->address ||
879                     client->lease->subnet_mask != lease->subnet_mask ||
880                     client->lease->router != lease->router) {
881                         r = DHCP_EVENT_IP_CHANGE;
882                 } else
883                         r = DHCP_EVENT_RENEW;
884
885                 client->lease = sd_dhcp_lease_unref(client->lease);
886         }
887
888         client->lease = lease;
889         lease = NULL;
890
891         log_dhcp_client(client, "ACK");
892
893         return r;
894 }
895
896 static uint64_t client_compute_timeout(sd_dhcp_client *client,
897                                        uint32_t lifetime, double factor) {
898         assert(client);
899         assert(client->request_sent);
900         assert(lifetime);
901
902         return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
903                 + (random_u32() & 0x1fffff);
904 }
905
906 static int client_set_lease_timeouts(sd_dhcp_client *client) {
907         usec_t time_now;
908         uint64_t lifetime_timeout;
909         uint64_t t2_timeout;
910         uint64_t t1_timeout;
911         char time_string[FORMAT_TIMESPAN_MAX];
912         int r;
913
914         assert(client);
915         assert(client->event);
916         assert(client->lease);
917         assert(client->lease->lifetime);
918
919         client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
920         client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
921         client->timeout_expire = sd_event_source_unref(client->timeout_expire);
922
923         /* don't set timers for infinite leases */
924         if (client->lease->lifetime == 0xffffffff)
925                 return 0;
926
927         r = sd_event_now(client->event, CLOCK_MONOTONIC, &time_now);
928         if (r < 0)
929                 return r;
930         assert(client->request_sent <= time_now);
931
932         /* convert the various timeouts from relative (secs) to absolute (usecs) */
933         lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
934         if (client->lease->t1 && client->lease->t2) {
935                 /* both T1 and T2 are given */
936                 if (client->lease->t1 < client->lease->t2 &&
937                     client->lease->t2 < client->lease->lifetime) {
938                         /* they are both valid */
939                         t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
940                         t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
941                 } else {
942                         /* discard both */
943                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
944                         client->lease->t2 = (client->lease->lifetime * 7) / 8;
945                         t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
946                         client->lease->t1 = client->lease->lifetime / 2;
947                 }
948         } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
949                 /* only T2 is given, and it is valid */
950                 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
951                 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
952                 client->lease->t1 = client->lease->lifetime / 2;
953                 if (t2_timeout <= t1_timeout) {
954                         /* the computed T1 would be invalid, so discard T2 */
955                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
956                         client->lease->t2 = (client->lease->lifetime * 7) / 8;
957                 }
958         } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
959                 /* only T1 is given, and it is valid */
960                 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
961                 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
962                 client->lease->t2 = (client->lease->lifetime * 7) / 8;
963                 if (t2_timeout <= t1_timeout) {
964                         /* the computed T2 would be invalid, so discard T1 */
965                         t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
966                         client->lease->t2 = client->lease->lifetime / 2;
967                 }
968         } else {
969                 /* fall back to the default timeouts */
970                 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
971                 client->lease->t1 = client->lease->lifetime / 2;
972                 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
973                 client->lease->t2 = (client->lease->lifetime * 7) / 8;
974         }
975
976         /* arm lifetime timeout */
977         r = sd_event_add_time(client->event, &client->timeout_expire,
978                               CLOCK_MONOTONIC,
979                               lifetime_timeout, 10 * USEC_PER_MSEC,
980                               client_timeout_expire, client);
981         if (r < 0)
982                 return r;
983
984         r = sd_event_source_set_priority(client->timeout_expire,
985                                          client->event_priority);
986         if (r < 0)
987                 return r;
988
989         log_dhcp_client(client, "lease expires in %s",
990                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
991                         lifetime_timeout - time_now, 0));
992
993         /* don't arm earlier timeouts if this has already expired */
994         if (lifetime_timeout <= time_now)
995                 return 0;
996
997         /* arm T2 timeout */
998         r = sd_event_add_time(client->event,
999                               &client->timeout_t2,
1000                               CLOCK_MONOTONIC,
1001                               t2_timeout,
1002                               10 * USEC_PER_MSEC,
1003                               client_timeout_t2, client);
1004         if (r < 0)
1005                 return r;
1006
1007         r = sd_event_source_set_priority(client->timeout_t2,
1008                                          client->event_priority);
1009         if (r < 0)
1010                 return r;
1011
1012         log_dhcp_client(client, "T2 expires in %s",
1013                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1014                         t2_timeout - time_now, 0));
1015
1016         /* don't arm earlier timeout if this has already expired */
1017         if (t2_timeout <= time_now)
1018                 return 0;
1019
1020         /* arm T1 timeout */
1021         r = sd_event_add_time(client->event,
1022                               &client->timeout_t1,
1023                               CLOCK_MONOTONIC,
1024                               t1_timeout, 10 * USEC_PER_MSEC,
1025                               client_timeout_t1, client);
1026         if (r < 0)
1027                 return r;
1028
1029         r = sd_event_source_set_priority(client->timeout_t1,
1030                                          client->event_priority);
1031         if (r < 0)
1032                 return r;
1033
1034         log_dhcp_client(client, "T1 expires in %s",
1035                         format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1036                         t1_timeout - time_now, 0));
1037
1038         return 0;
1039 }
1040
1041 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1042                                  int len) {
1043         DHCP_CLIENT_DONT_DESTROY(client);
1044         int r = 0, notify_event = 0;
1045
1046         assert(client);
1047         assert(client->event);
1048         assert(message);
1049
1050         if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1051                 log_dhcp_client(client, "not a DHCP message: ignoring");
1052                 return 0;
1053         }
1054
1055         if (message->op != BOOTREPLY) {
1056                 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1057                 return 0;
1058         }
1059
1060         if (be32toh(message->xid) != client->xid) {
1061                 log_dhcp_client(client, "received xid (%u) does not match "
1062                                 "expected (%u): ignoring",
1063                                 be32toh(message->xid), client->xid);
1064                 return 0;
1065         }
1066
1067         if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
1068                 log_dhcp_client(client, "not an ethernet packet");
1069                 return 0;
1070         }
1071
1072         if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
1073                    ETH_ALEN)) {
1074                 log_dhcp_client(client, "received chaddr does not match "
1075                                 "expected: ignoring");
1076                 return 0;
1077         }
1078
1079         switch (client->state) {
1080         case DHCP_STATE_SELECTING:
1081
1082                 r = client_handle_offer(client, message, len);
1083                 if (r >= 0) {
1084
1085                         client->timeout_resend =
1086                                 sd_event_source_unref(client->timeout_resend);
1087
1088                         client->state = DHCP_STATE_REQUESTING;
1089                         client->attempt = 1;
1090
1091                         r = sd_event_add_time(client->event,
1092                                               &client->timeout_resend,
1093                                               CLOCK_MONOTONIC,
1094                                               0, 0,
1095                                               client_timeout_resend, client);
1096                         if (r < 0)
1097                                 goto error;
1098
1099                         r = sd_event_source_set_priority(client->timeout_resend,
1100                                                          client->event_priority);
1101                         if (r < 0)
1102                                 goto error;
1103                 } else if (r == -ENOMSG)
1104                         /* invalid message, let's ignore it */
1105                         return 0;
1106
1107                 break;
1108
1109         case DHCP_STATE_REBOOTING:
1110         case DHCP_STATE_REQUESTING:
1111         case DHCP_STATE_RENEWING:
1112         case DHCP_STATE_REBINDING:
1113
1114                 r = client_handle_ack(client, message, len);
1115                 if (r == DHCP_EVENT_NO_LEASE) {
1116
1117                         client->timeout_resend =
1118                                 sd_event_source_unref(client->timeout_resend);
1119
1120                         if (client->state == DHCP_STATE_REBOOTING) {
1121                                 r = client_initialize(client);
1122                                 if (r < 0)
1123                                         goto error;
1124
1125                                 r = client_start(client);
1126                                 if (r < 0)
1127                                         goto error;
1128
1129                                 log_dhcp_client(client, "REBOOTED");
1130                         }
1131
1132                         goto error;
1133                 } else if (r >= 0) {
1134                         client->timeout_resend =
1135                                 sd_event_source_unref(client->timeout_resend);
1136
1137                         if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1138                                    DHCP_STATE_REBOOTING))
1139                                 notify_event = DHCP_EVENT_IP_ACQUIRE;
1140                         else if (r != DHCP_EVENT_IP_ACQUIRE)
1141                                 notify_event = r;
1142
1143                         client->state = DHCP_STATE_BOUND;
1144                         client->attempt = 1;
1145
1146                         client->last_addr = client->lease->address;
1147
1148                         r = client_set_lease_timeouts(client);
1149                         if (r < 0)
1150                                 goto error;
1151
1152                         if (notify_event) {
1153                                 client_notify(client, notify_event);
1154                                 if (client->state == DHCP_STATE_STOPPED)
1155                                         return 0;
1156                         }
1157
1158                         client->receive_message =
1159                                 sd_event_source_unref(client->receive_message);
1160                         client->fd = asynchronous_close(client->fd);
1161                 } else if (r == -ENOMSG)
1162                         /* invalid message, let's ignore it */
1163                         return 0;
1164
1165                 break;
1166
1167         case DHCP_STATE_INIT:
1168         case DHCP_STATE_INIT_REBOOT:
1169         case DHCP_STATE_BOUND:
1170
1171                 break;
1172
1173         case DHCP_STATE_STOPPED:
1174                 r = -EINVAL;
1175                 goto error;
1176         }
1177
1178 error:
1179         if (r < 0 || r == DHCP_EVENT_NO_LEASE)
1180                 client_stop(client, r);
1181
1182         return r;
1183 }
1184
1185 static int client_receive_message_udp(sd_event_source *s, int fd,
1186                                       uint32_t revents, void *userdata) {
1187         sd_dhcp_client *client = userdata;
1188         _cleanup_free_ DHCPMessage *message = NULL;
1189         int buflen = 0, len, r;
1190
1191         assert(s);
1192         assert(client);
1193
1194         r = ioctl(fd, FIONREAD, &buflen);
1195         if (r < 0)
1196                 return r;
1197
1198         if (buflen < 0)
1199                 /* this can't be right */
1200                 return -EIO;
1201
1202         message = malloc0(buflen);
1203         if (!message)
1204                 return -ENOMEM;
1205
1206         len = read(fd, message, buflen);
1207         if (len < 0) {
1208                 log_dhcp_client(client, "could not receive message from UDP "
1209                                 "socket: %m");
1210                 return 0;
1211         } else if ((size_t)len < sizeof(DHCPMessage))
1212                 return 0;
1213
1214         return client_handle_message(client, message, len);
1215 }
1216
1217 static int client_receive_message_raw(sd_event_source *s, int fd,
1218                                       uint32_t revents, void *userdata) {
1219         sd_dhcp_client *client = userdata;
1220         _cleanup_free_ DHCPPacket *packet = NULL;
1221         uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1222         struct iovec iov = {};
1223         struct msghdr msg = {
1224                 .msg_iov = &iov,
1225                 .msg_iovlen = 1,
1226                 .msg_control = cmsgbuf,
1227                 .msg_controllen = sizeof(cmsgbuf),
1228         };
1229         struct cmsghdr *cmsg;
1230         bool checksum = true;
1231         int buflen = 0, len, r;
1232
1233         assert(s);
1234         assert(client);
1235
1236         r = ioctl(fd, FIONREAD, &buflen);
1237         if (r < 0)
1238                 return r;
1239
1240         if (buflen < 0)
1241                 /* this can't be right */
1242                 return -EIO;
1243
1244         packet = malloc0(buflen);
1245         if (!packet)
1246                 return -ENOMEM;
1247
1248         iov.iov_base = packet;
1249         iov.iov_len = buflen;
1250
1251         len = recvmsg(fd, &msg, 0);
1252         if (len < 0) {
1253                 log_dhcp_client(client, "could not receive message from raw "
1254                                 "socket: %m");
1255                 return 0;
1256         } else if ((size_t)len < sizeof(DHCPPacket))
1257                 return 0;
1258
1259         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1260                 if (cmsg->cmsg_level == SOL_PACKET &&
1261                     cmsg->cmsg_type == PACKET_AUXDATA &&
1262                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1263                         struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1264
1265                         checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1266                         break;
1267                 }
1268         }
1269
1270         r = dhcp_packet_verify_headers(packet, len, checksum);
1271         if (r < 0)
1272                 return 0;
1273
1274         len -= DHCP_IP_UDP_SIZE;
1275
1276         return client_handle_message(client, &packet->dhcp, len);
1277 }
1278
1279 int sd_dhcp_client_start(sd_dhcp_client *client) {
1280         int r;
1281
1282         assert_return(client, -EINVAL);
1283
1284         r = client_initialize(client);
1285         if (r < 0)
1286                 return r;
1287
1288         if (client->last_addr)
1289                 client->state = DHCP_STATE_INIT_REBOOT;
1290
1291         r = client_start(client);
1292         if (r >= 0)
1293                 log_dhcp_client(client, "STARTED on ifindex %u with address %s",
1294                                 client->index,
1295                                 ether_ntoa(&client->client_id.mac_addr));
1296
1297         return r;
1298 }
1299
1300 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1301         DHCP_CLIENT_DONT_DESTROY(client);
1302
1303         assert_return(client, -EINVAL);
1304
1305         client_stop(client, DHCP_EVENT_STOP);
1306         client->state = DHCP_STATE_STOPPED;
1307
1308         return 0;
1309 }
1310
1311 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1312                                 int priority) {
1313         int r;
1314
1315         assert_return(client, -EINVAL);
1316         assert_return(!client->event, -EBUSY);
1317
1318         if (event)
1319                 client->event = sd_event_ref(event);
1320         else {
1321                 r = sd_event_default(&client->event);
1322                 if (r < 0)
1323                         return 0;
1324         }
1325
1326         client->event_priority = priority;
1327
1328         return 0;
1329 }
1330
1331 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1332         assert_return(client, -EINVAL);
1333
1334         client->event = sd_event_unref(client->event);
1335
1336         return 0;
1337 }
1338
1339 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1340         if (!client)
1341                 return NULL;
1342
1343         return client->event;
1344 }
1345
1346 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1347         if (client)
1348                 assert_se(REFCNT_INC(client->n_ref) >= 2);
1349
1350         return client;
1351 }
1352
1353 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1354         if (client && REFCNT_DEC(client->n_ref) <= 0) {
1355                 log_dhcp_client(client, "FREE");
1356
1357                 client_initialize(client);
1358
1359                 client->receive_message =
1360                         sd_event_source_unref(client->receive_message);
1361
1362                 sd_dhcp_client_detach_event(client);
1363
1364                 sd_dhcp_lease_unref(client->lease);
1365
1366                 free(client->req_opts);
1367                 free(client);
1368         }
1369
1370         return NULL;
1371 }
1372
1373 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1374         _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
1375
1376         assert_return(ret, -EINVAL);
1377
1378         client = new0(sd_dhcp_client, 1);
1379         if (!client)
1380                 return -ENOMEM;
1381
1382         client->n_ref = REFCNT_INIT;
1383         client->state = DHCP_STATE_INIT;
1384         client->index = -1;
1385         client->fd = -1;
1386         client->attempt = 1;
1387
1388         client->req_opts_size = ELEMENTSOF(default_req_opts);
1389
1390         client->req_opts = memdup(default_req_opts, client->req_opts_size);
1391         if (!client->req_opts)
1392                 return -ENOMEM;
1393
1394         *ret = client;
1395         client = NULL;
1396
1397         return 0;
1398 }