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