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