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