]> git.saurik.com Git - apple/mdnsresponder.git/blob - ServiceRegistration/srp-client.c
mDNSResponder-1310.80.1.tar.gz
[apple/mdnsresponder.git] / ServiceRegistration / srp-client.c
1 /* srp-client.c
2 *
3 * Copyright (c) 2018-2019 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * SRP Client
18 *
19 * DNSServiceRegister API for SRP. See dns_sd.h for details on the API.
20 */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <strings.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <inttypes.h>
28 #ifdef THREAD_DEVKIT
29 #include "../mDNSShared/dns_sd.h"
30 #else
31 #include <dns_sd.h>
32 #include <arpa/inet.h>
33 #endif
34 #include "srp.h"
35 #include "srp-api.h"
36 #include "dns-msg.h"
37 #include "srp-crypto.h"
38
39 typedef struct client_state client_state_t;
40
41 typedef struct service_addr service_addr_t;
42 struct service_addr {
43 service_addr_t *NULLABLE next;
44 dns_rr_t rr;
45 uint8_t port[2];
46 };
47
48 typedef struct _DNSServiceRef_t reg_state_t;
49 typedef struct update_context {
50 void *udp_context;
51 void *message;
52 client_state_t *NONNULL client;
53 service_addr_t *server;
54 service_addr_t *interfaces;
55 size_t message_length;
56 uint32_t next_retransmission_time;
57 uint32_t next_attempt_time;
58 uint32_t lease_time;
59 uint32_t key_lease_time;
60 uint32_t serial;
61 bool notified; // Callers have been notified.
62 bool connected; // UDP context is connected.
63 bool removing; // We are removing the current registration(s)
64 } update_context_t;
65
66 struct _DNSServiceRef_t {
67 reg_state_t *NULLABLE next;
68 uint32_t serial;
69 DNSServiceFlags flags;
70 uint32_t interfaceIndex;
71 char *NULLABLE name;
72 char *NULLABLE regtype;
73 char *NULLABLE domain;
74 char *NULLABLE host;
75 int port;
76 uint16_t txtLen;
77 void *NULLABLE txtRecord;
78 DNSServiceRegisterReply callback;
79 bool succeeded;
80 bool called_back;
81 void *NULLABLE context;
82 };
83
84 struct client_state {
85 client_state_t *next;
86 reg_state_t *registrations;
87 char *hostname;
88 int hostname_rename_number; // If we've had a naming conflict, this will be nonzero.
89 srp_hostname_conflict_callback_t hostname_conflict_callback;
90 srp_key_t *key;
91 void *os_context;
92 uint32_t lease_time;
93 uint32_t key_lease_time;
94 uint32_t registration_serial;
95 uint32_t srp_max_attempt_interval;
96 uint32_t srp_max_retry_interval;
97 service_addr_t stable_server;
98 bool srp_server_synced;
99
100 int client_serial;
101
102 // Currently we only ever have one update in flight. If we decide we need to send another,
103 // we need to cancel the one we're currently doing.
104 update_context_t *active_update;
105 };
106
107 // Implementation of SRP network entry points, which can be called by the network implementation on the
108 // hosting platform.
109
110 static bool network_state_changed = false;
111 static bool doing_refresh = false;
112 static service_addr_t *interfaces;
113 static service_addr_t *servers;
114 static service_addr_t *interface_refresh_state;
115 static service_addr_t *server_refresh_state;
116 static uint8_t no_port[2];
117
118 client_state_t *clients;
119 client_state_t *current_client;
120
121 // Forward references
122 static int do_srp_update(client_state_t *client, bool definite);
123 static void udp_response(void *v_update_context, void *v_message, size_t message_length);
124 static dns_wire_t *NULLABLE generate_srp_update(client_state_t *client, uint32_t update_lease_time,
125 uint32_t update_key_lease_time, size_t *NONNULL p_length,
126 service_addr_t *NONNULL server, uint32_t serial, bool remove);
127 static bool srp_is_network_active(void);
128
129 #define VALIDATE_IP_ADDR \
130 if ((rrtype != dns_rrtype_a && rrtype != dns_rrtype_aaaa) || \
131 (rrtype == dns_rrtype_a && rdlen != 4) || \
132 (rrtype == dns_rrtype_aaaa && rdlen != 16)) { \
133 return kDNSServiceErr_Invalid; \
134 }
135
136 // Call this before calling anything else. Context will be passed back whenever the srp code
137 // calls any of the host functions.
138 int
139 srp_host_init(void *context)
140 {
141 client_state_t *new_client = calloc(1, sizeof(*new_client));
142 if (new_client == NULL) {
143 return kDNSServiceErr_NoMemory;
144 }
145 new_client->os_context = context;
146 new_client->lease_time = 3600; // 1 hour for registration leases
147 new_client->key_lease_time = 604800; // 7 days for key leases
148 new_client->registration_serial = 0;
149 new_client->srp_max_attempt_interval = 1000 * 60 * 60; // By default, never wait longer than an hour to do another
150 // registration attempt.
151 new_client->srp_max_retry_interval = 1000 * 15; // Default retry interval is 15 seconds--three attempts.
152
153 current_client = new_client;
154 new_client->next = clients;
155 clients = current_client;
156 return kDNSServiceErr_NoError;
157 }
158
159 int
160 srp_host_key_reset(void)
161 {
162 if (current_client->key != NULL) {
163 srp_keypair_free(current_client->key);
164 current_client->key = NULL;
165 }
166 return srp_reset_key("com.apple.srp-client.host-key", current_client->os_context);
167 }
168
169 int
170 srp_set_lease_times(uint32_t new_lease_time, uint32_t new_key_lease_time)
171 {
172 current_client->lease_time = new_lease_time;
173 current_client->key_lease_time = new_key_lease_time;
174 return kDNSServiceErr_NoError;
175 }
176
177 static void
178 sync_from_stable_storage(update_context_t *update)
179 {
180 service_addr_t *server;
181 client_state_t *client = update->client;
182 if (!client->srp_server_synced) {
183 client->srp_server_synced =
184 srp_get_last_server(&client->stable_server.rr.type, (uint8_t *)&client->stable_server.rr.data,
185 sizeof(client->stable_server.rr.data), &client->stable_server.port[0],
186 client->os_context);
187 // Nothing read.
188 if (!client->srp_server_synced) {
189 return;
190 }
191 } else {
192 if (update->server != NULL) {
193 return;
194 }
195 }
196
197 // See if one of the advertised servers is the one we last updated.
198 for (server = servers; server; server = server->next) {
199 if (server->rr.type == client->stable_server.rr.type &&
200 !memcmp(&server->port, &client->stable_server.port, 2) &&
201 ((server->rr.type == dns_rrtype_a && !memcmp(&server->rr.data, &client->stable_server.rr.data, 4)) ||
202 (server->rr.type == dns_rrtype_aaaa && !memcmp(&server->rr.data, &client->stable_server.rr.data, 16))))
203 {
204 update->server = server;
205 return;
206 }
207 }
208 }
209
210 static void
211 sync_to_stable_storage(update_context_t *update)
212 {
213 client_state_t *client = update->client;
214 if (!client->srp_server_synced) {
215 client->srp_server_synced =
216 srp_save_last_server(client->stable_server.rr.type, (uint8_t *)&client->stable_server.rr.data,
217 client->stable_server.rr.type == dns_rrtype_a ? 4 : 16,
218 client->stable_server.port, client->os_context);
219 }
220 }
221
222 // Find an address on a list of addresses.
223 static service_addr_t **
224 find_address(service_addr_t **addrs, const uint8_t *port, uint16_t rrtype, const uint8_t *rdata, uint16_t rdlen)
225 {
226 service_addr_t *addr, **p_addr = addrs;
227
228 while (*p_addr != NULL) {
229 addr = *p_addr;
230 if (addr->rr.type == rrtype && !memcmp(&addr->rr.data, rdata, rdlen) && !memcmp(addr->port, port, 2)) {
231 break;
232 }
233 p_addr = &addr->next;
234 }
235 return p_addr;
236 }
237
238 // Worker function to add an address and notice whether the network state has changed (so as to trigger a
239 // refresh).
240 static int
241 add_address(service_addr_t **list, service_addr_t **refresh,
242 const uint8_t *port, uint16_t rrtype, const uint8_t *rdata, uint16_t rdlen)
243 {
244 service_addr_t *addr, **p_addr, **p_refresh;
245
246 VALIDATE_IP_ADDR;
247
248 // See if the address is on the refresh list.
249 p_refresh = find_address(refresh, port, rrtype, rdata, rdlen);
250
251 // See also if it's on the address list (shouldn't be on both). This also finds the end of the list.
252 p_addr = find_address(list, port, rrtype, rdata, rdlen);
253 if (*p_addr != NULL) {
254 return kDNSServiceErr_NoError;
255 }
256
257 if (*p_refresh != NULL) {
258 addr = *p_refresh;
259
260 // This shouldn't happen, but if it does, free the old address.
261 if (*p_addr != NULL) {
262 ERROR("duplicate address during refresh!");
263 free(addr);
264 return kDNSServiceErr_NoError;
265 }
266
267 *p_refresh = addr->next;
268 addr->next = NULL;
269 *p_addr = addr;
270
271 // In this case, the network state has not changed.
272 return kDNSServiceErr_NoError;
273 }
274
275 addr = calloc(1, sizeof *addr);
276 if (addr == NULL) {
277 return kDNSServiceErr_NoMemory;
278 }
279 addr->rr.type = rrtype;
280 addr->rr.qclass = dns_qclass_in;
281 memcpy(&addr->rr.data, rdata, rdlen);
282 memcpy(&addr->port, port, 2);
283 *p_addr = addr;
284 network_state_changed = true;
285
286 // Print IPv6 address directly here because the code has to be portable for ADK, and OpenThread environment
287 // has no support for INET6_ADDRSTRLEN.
288 INFO("added " PUB_S_SRP
289 " address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x port %u (%04x)",
290 *list == servers ? "server" : "interface",
291 rdata[0], rdata[1], rdata[2], rdata[3], rdata[4], rdata[5], rdata[6], rdata[7],
292 rdata[8], rdata[9], rdata[10], rdata[11], rdata[12], rdata[13], rdata[14], rdata[15],
293 port != NULL ? (port[0] << 8 | port[1]) : 0, port != NULL ? (port[0] << 8 | port[1]) : 0);
294
295 return kDNSServiceErr_NoError;
296 }
297
298 // Called when a new address is configured that should be advertised. This can be called during a refresh,
299 // in which case it doesn't mark the network state as changed if the address was already present.
300 int
301 srp_add_interface_address(uint16_t rrtype, const uint8_t *NONNULL rdata, uint16_t rdlen)
302 {
303 return add_address(&interfaces, &interface_refresh_state, no_port, rrtype, rdata, rdlen);
304 }
305
306 // Called whenever the SRP server address changes or the SRP server becomes newly reachable. This can be
307 // called during a refresh, in which case it doesn't mark the network state as changed if the address was
308 // already present.
309 int
310 srp_add_server_address(const uint8_t *port, uint16_t rrtype, const uint8_t *NONNULL rdata, uint16_t rdlen)
311 {
312 VALIDATE_IP_ADDR;
313
314 return add_address(&servers, &server_refresh_state, port, rrtype, rdata, rdlen);
315 }
316
317 // Called when the node knows its hostname (usually once). The callback is called if we try to do an SRP
318 // update and find out that the hostname is in use; in this case, the callback is expected to generate a new
319 // hostname and re-register it. It is permitted to call srp_set_hostname() from the callback.
320 // If the hostname is changed by the callback, then it is used immediately on return from the callback;
321 // if the hostname is changed in any other situation, nothing is done with the new name until
322 // srp_network_state_stable() is called.
323 int
324 srp_set_hostname(const char *NONNULL name, srp_hostname_conflict_callback_t callback)
325 {
326 if (current_client->hostname != NULL) {
327 free(current_client->hostname);
328 }
329 current_client->hostname = strdup(name);
330 if (current_client->hostname == NULL) {
331 return kDNSServiceErr_NoMemory;
332 }
333 current_client->hostname_conflict_callback = callback;
334 network_state_changed = true;
335 return kDNSServiceErr_NoError;
336 }
337
338 // Called when a network state change is complete (that is, all new addresses have been saved and
339 // any update to the SRP server address has been provided). This is only needed when not using the
340 // refresh mechanism.
341 static bool
342 srp_is_network_active(void)
343 {
344 INFO("srp_is_network_active: nsc = %d servers = %p interfaces = %p, hostname = " PRI_S_SRP,
345 network_state_changed, servers, interfaces,
346 current_client->hostname ? current_client->hostname : "<not set>");
347 return servers != NULL && interfaces != NULL && current_client->hostname != NULL;
348 }
349
350 int
351 srp_network_state_stable(void)
352 {
353 client_state_t *client;
354 int status = kDNSServiceErr_NoError;
355 if (network_state_changed && srp_is_network_active()) {
356 network_state_changed = false;
357 for (client = clients; client; client = client->next) {
358 int ret = do_srp_update(client, false);
359 // In the normal case, there will only be one client, and therefore one return status. For testing,
360 // we allow more than one client; if we get an error here, we return it, but we still launch all the
361 // updates.
362 if (ret != kDNSServiceErr_NoError && status == kDNSServiceErr_NoError) {
363 status = ret;
364 }
365 }
366 }
367 return kDNSServiceErr_NoError;
368 }
369
370 // Worker function to delete a server or interface address that was previously configured.
371 static int
372 delete_address(service_addr_t **list, const uint8_t *port, uint16_t rrtype, const uint8_t *NONNULL rdata,
373 uint16_t rdlen)
374 {
375 service_addr_t *addr, **p_addr;
376
377 // Delete API and refresh API are incompatible.
378 if (doing_refresh) {
379 return kDNSServiceErr_BadState;
380 }
381 VALIDATE_IP_ADDR;
382
383 // See if we know this address.
384 p_addr = find_address(list, port, rrtype, rdata, rdlen);
385 if (*p_addr != NULL) {
386 addr = *p_addr;
387 *p_addr = addr->next;
388 free(addr);
389 network_state_changed = true;
390 return kDNSServiceErr_NoError;
391 }
392 return kDNSServiceErr_NoSuchRecord;
393 }
394
395 // Delete a previously-configured SRP server address. This should not be done during a refresh.
396 int
397 srp_delete_interface_address(uint16_t rrtype, const uint8_t *NONNULL rdata, uint16_t rdlen)
398 {
399 return delete_address(&interfaces, no_port, rrtype, rdata, rdlen);
400 }
401
402 // Delete a previously-configured SRP server address. This should not be done during a refresh.
403 int
404 srp_delete_server_address(uint16_t rrtype, const uint8_t *port, const uint8_t *NONNULL rdata, uint16_t rdlen)
405 {
406 return delete_address(&servers, port, rrtype, rdata, rdlen);
407 }
408
409 // Call this to start an address refresh. This makes sense to do in cases where the caller
410 // is not tracking changes, but rather is just doing a full refresh whenever the network state
411 // is seen to have changed. When the refresh is done, if any addresses were added or removed,
412 // network_state_changed will be true, and so a call to dnssd_network_state_change_finished()
413 // will trigger an update; if nothing changed, no update will be sent.
414 int
415 srp_start_address_refresh(void)
416 {
417 if (doing_refresh) {
418 return kDNSServiceErr_BadState;
419 }
420 doing_refresh = true;
421 interface_refresh_state = interfaces;
422 server_refresh_state = servers;
423 interfaces = NULL;
424 servers = NULL;
425 network_state_changed = false;
426 return kDNSServiceErr_NoError;
427 }
428
429 // Call this when the address refresh is done. This invokes srp_network_state_stable().
430 int
431 srp_finish_address_refresh(void)
432 {
433 service_addr_t *addr, *next;
434 int i;
435 if (!doing_refresh) {
436 return kDNSServiceErr_BadState;
437 }
438 for (i = 0; i < 2; i++) {
439 if (i == 0) {
440 next = server_refresh_state;
441 server_refresh_state = NULL;
442 } else {
443 next = interface_refresh_state;
444 interface_refresh_state = NULL;
445 }
446 if (next != NULL) {
447 network_state_changed = true;
448 }
449 while (next) {
450 uint8_t *rdata = (uint8_t *)&next->rr.data;
451 // Print IPv6 address directly here because the code has to be portable for ADK, and OpenThread environment
452 // has no support for INET6_ADDRSTRLEN.
453 INFO("deleted " PUB_S_SRP
454 " address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x port %u (%x)",
455 i ? "interface" : "server",
456 rdata[0], rdata[1], rdata[2], rdata[3], rdata[4], rdata[5], rdata[6], rdata[7],
457 rdata[8], rdata[9], rdata[10], rdata[11], rdata[12], rdata[13], rdata[14], rdata[15],
458 (next->port[0] << 8) | next->port[1], (next->port[0] << 8) | next->port[1]);
459 addr = next;
460 next = addr->next;
461 free(addr);
462 }
463 }
464 doing_refresh = false;
465 return srp_network_state_stable();
466 }
467
468 // Implementation of the API that the application will call to update the TXT record after having registered
469 // a service previously with a different TXT record. In principle this can also update a record added with
470 // DNSServiceAddRecord or DNSServiceRegisterRecord, but we don't support those APIs at present.
471
472 DNSServiceErrorType
473 DNSServiceUpdateRecord(DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags,
474 uint16_t rdlen, const void *rdata, uint32_t ttl)
475 {
476 reg_state_t *registration;
477 void *txtRecord = NULL;
478
479 (void)RecordRef;
480 (void)flags;
481 (void)ttl;
482
483 if (sdRef == NULL || RecordRef != NULL || rdata == NULL) {
484 return kDNSServiceErr_Invalid;
485 }
486
487 // Add it to the list (so it will appear valid to DNSServiceRefDeallocate()).
488 for (registration = current_client->registrations; registration != NULL; registration = registration->next) {
489 if (registration == sdRef) {
490 break;
491 }
492 }
493 if (registration == NULL) {
494 return kDNSServiceErr_BadReference;
495 }
496
497 if (rdlen != 0) {
498 txtRecord = malloc(rdlen);
499 if (txtRecord == NULL) {
500 return kDNSServiceErr_NoMemory;
501 }
502 memcpy(txtRecord, rdata, rdlen);
503 } else {
504 registration->txtRecord = NULL;
505 }
506
507 if (registration->txtRecord != NULL) {
508 free(registration->txtRecord);
509 }
510
511 registration->txtRecord = txtRecord;
512 registration->txtLen = rdlen;
513 network_state_changed = true;
514 return kDNSServiceErr_NoError;
515 }
516
517 // Implementation of the API that applications will call to register services. This is independent of the
518 // hosting platform API.
519 DNSServiceErrorType
520 DNSServiceRegister(DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
521 const char *NULLABLE name, const char *NULLABLE regtype, const char *NULLABLE domain,
522 const char *NULLABLE host, uint16_t port,
523 uint16_t txtLen, const void *txtRecord,
524 DNSServiceRegisterReply callBack, void *context)
525 {
526 reg_state_t **rp, *reg = calloc(1, sizeof *reg);
527 if (reg == NULL) {
528 return kDNSServiceErr_NoMemory;
529 }
530
531 // Add it to the list (so it will appear valid to DNSServiceRefDeallocate()).
532 rp = &current_client->registrations;
533 while (*rp) {
534 rp = &((*rp)->next);
535 }
536 *rp = reg;
537
538 // If we don't already have a hostname, use the one from the registration.
539 if (current_client->hostname == NULL) {
540 srp_set_hostname(host, NULL);
541 }
542
543 reg->serial = current_client->registration_serial++;
544 reg->flags = flags;
545 reg->interfaceIndex = interfaceIndex;
546 reg->called_back = true;
547 #define stashName(thing) \
548 if (thing != NULL) { \
549 reg->thing = strdup(thing); \
550 if (reg->thing == NULL) { \
551 DNSServiceRefDeallocate(reg); \
552 return kDNSServiceErr_NoMemory; \
553 } \
554 } else { \
555 reg->thing = NULL; \
556 }
557 stashName(name);
558 stashName(regtype);
559 stashName(domain);
560 stashName(host);
561 reg->port = port;
562 reg->txtLen = txtLen;
563 if (txtLen != 0) {
564 reg->txtRecord = malloc(txtLen);
565 if (reg->txtRecord == NULL) {
566 DNSServiceRefDeallocate(reg);
567 return kDNSServiceErr_NoMemory;
568 }
569 memcpy(reg->txtRecord, txtRecord, txtLen);
570 } else {
571 reg->txtRecord = NULL;
572 }
573 reg->callback = callBack;
574 reg->context = context;
575 *sdRef = reg;
576 network_state_changed = true;
577 return kDNSServiceErr_NoError;
578 }
579
580 void
581 DNSServiceRefDeallocate(DNSServiceRef sdRef)
582 {
583 reg_state_t **rp, *reg = NULL;
584 bool found = false;
585 client_state_t *client;
586
587 if (sdRef == NULL) {
588 return;
589 }
590
591 for (client = clients; client; client = client->next) {
592 // Remove it from the list.
593 rp = &client->registrations;
594 reg = *rp;
595 while (*rp) {
596 if (reg == sdRef) {
597 *rp = reg->next;
598 found = true;
599 break;
600 }
601 rp = &((*rp)->next);
602 reg = *rp;
603 }
604
605 if (found) {
606 break;
607 }
608 }
609
610 // This avoids a bogus free.
611 if (!found || reg == NULL) {
612 return;
613 }
614 if (reg->name != NULL) {
615 free(reg->name);
616 }
617 if (reg->regtype != NULL) {
618 free(reg->regtype);
619 }
620 if (reg->domain != NULL) {
621 free(reg->domain);
622 }
623 if (reg->host != NULL) {
624 free(reg->host);
625 }
626 if (reg->txtRecord != NULL) {
627 free(reg->txtRecord);
628 }
629 free(reg);
630 }
631
632 static void
633 update_finalize(update_context_t *update)
634 {
635 client_state_t *client = update->client;
636 if (update->udp_context != NULL) {
637 srp_deactivate_udp_context(client->os_context, update->udp_context);
638 }
639 if (update->message != NULL) {
640 free(update->message);
641 }
642 if (update->interfaces != NULL) {
643 free(update->interfaces);
644 }
645 free(update);
646 }
647
648 static void
649 do_callbacks(client_state_t *client, uint32_t serial, int err, bool succeeded)
650 {
651 reg_state_t *rp;
652 bool work;
653
654 // The callback can modify the list, so we use a marker to remember where we are in the list rather
655 // than remembering a pointer which could be invalidated. If a callback adds a registration, that
656 // registration doesn't get called because called_back is set to true when a registration is added.
657 for (rp = client->registrations; rp; rp = rp->next) {
658 if (rp->serial <= serial) {
659 rp->called_back = false;
660 }
661 }
662 do {
663 work = false;
664 for (rp = client->registrations; rp; rp = rp->next) {
665 if (rp->serial > serial || rp->callback == NULL || rp->called_back) {
666 continue;
667 }
668 work = true;
669 rp->called_back = true;
670 if (rp->callback != NULL) {
671 rp->callback(rp, kDNSServiceFlagsAdd, err, rp->name, rp->regtype, rp->domain, rp->context);
672 }
673 if (succeeded) {
674 rp->succeeded = true;
675 }
676 }
677 } while (work);
678 }
679
680 static void
681 udp_retransmit(void *v_update_context)
682 {
683 update_context_t *context = v_update_context;
684 client_state_t *client;
685 service_addr_t *next_server = NULL;
686 int err;
687
688 client = context->client;
689
690 if (!srp_is_network_active()) {
691 INFO("udp_retransmit: network is down, discontinuing renewals.");
692 if (client->active_update != NULL) {
693 update_finalize(client->active_update);
694 client->active_update = NULL;
695 }
696 return;
697 }
698 // It shouldn't be possible for this to happen.
699 if (client->active_update == NULL) {
700 INFO("udp_retransmit: no active update for " PRI_S_SRP " (%p).",
701 client->hostname ? client->hostname : "<null>", client);
702 return;
703 }
704 INFO("udp_retransmit: next_attempt %" PRIu32 " next_retransmission %" PRIu32 " for " PRI_S_SRP " (%p)",
705 context->next_attempt_time, context->next_retransmission_time,
706 client->hostname ? client->hostname : "<null>", client);
707
708 // If next retransmission time is zero, this means that we gave up our last attempt to register, and have
709 // now waited long enough to try again. We will then use an exponential backoff for 90 seconds before giving
710 // up again; if we give up again, we will wait longer to retry, up to an hour.
711 if (context->next_retransmission_time == 0) {
712 // If there are no servers, we don't need to schedule a re-attempt: when a server is seen, we will do
713 // an update immediately.
714 if (servers == NULL) {
715 return;
716 }
717 next_server = servers;
718
719 // If this attempt fails, don't try again for a while longer, but limit the retry interval to an hour.
720 context->next_attempt_time *= 2;
721 if (context->next_attempt_time > client->srp_max_attempt_interval) {
722 context->next_attempt_time = client->srp_max_attempt_interval;
723 }
724 context->next_retransmission_time = 2000; // Next retry will be in two seconds.
725 }
726 // If this would be our fourth retry on a particular server, try the next server.
727 else if (context->next_retransmission_time > client->srp_max_retry_interval) {
728 // If we are removing, there is no point in trying the next server--just give up and report a timeout.
729 if (context->removing) {
730 do_callbacks(client, context->serial, kDNSServiceErr_Timeout, false);
731 // Once the goodbye retransmission has timed out, we're done.
732 return;
733 }
734 for (next_server = servers; next_server; next_server = next_server->next) {
735 if (next_server == context->server) {
736 // We're going to use the next server after the one we just tried. If we run out of servers,
737 // we'll give up for a while.
738 next_server = next_server->next;
739 break;
740 }
741 }
742
743 // If we run off the end of the list, give up for a bit.
744 if (next_server == NULL) {
745 context->next_retransmission_time = 0;
746 } else {
747 context->next_retransmission_time = 2000;
748 }
749 }
750 // Otherwise, we are still trying to win with a particular server, so back off exponentially.
751 else {
752 context->next_retransmission_time *= 2;
753 }
754
755 // If we are giving up on the current server, get rid of any udp state.
756 if (context->next_retransmission_time == 0 || next_server != NULL) {
757 if (next_server != NULL) {
758 context->server = next_server;
759 }
760 srp_disconnect_udp(context->udp_context);
761 context->connected = false;
762 if (context->message != NULL) {
763 free(context->message);
764 }
765 context->message = NULL;
766 context->message_length = 0;
767 }
768
769 // If we are not giving up, send the next packet.
770 if (context->server != NULL && context->next_retransmission_time != 0) {
771 if (!context->connected) {
772 // Create a UDP context for this transaction.
773 err = srp_connect_udp(context->udp_context, context->server->port, servers->rr.type,
774 (uint8_t *)&context->server->rr.data,
775 context->server->rr.type == dns_rrtype_a ? 4 : 16);
776 // In principle if it fails here, it might succeed later, so we just don't send a packet and let
777 // the timeout take care of it.
778 if (err != kDNSServiceErr_NoError) {
779 ERROR("udp_retransmit: error %d creating udp context.", err);
780 } else {
781 context->connected = true;
782 }
783 }
784
785 if (context->message == NULL) {
786 context->message = generate_srp_update(client, client->lease_time, client->key_lease_time, &context->message_length,
787 context->server, context->serial, context->removing);
788 if (context->message == NULL) {
789 ERROR("No memory for message.");
790 return;
791 }
792 }
793
794 if (context->connected) {
795 // Send the datagram to the server
796 err = srp_send_datagram(client->os_context, context->udp_context, context->message, context->message_length);
797 if (err != kDNSServiceErr_NoError) {
798 ERROR("udp_retransmit: error %d sending a datagram.", err);
799 }
800 }
801 }
802
803 // If we've given up for now, schedule a next attempt; otherwise, schedule the next retransmission.
804 if (context->next_retransmission_time == 0) {
805 err = srp_set_wakeup(client->os_context, context->udp_context, context->next_attempt_time, udp_retransmit);
806 } else {
807 err = srp_set_wakeup(client->os_context, context->udp_context,
808 context->next_retransmission_time - 512 + srp_random16() % 1024, udp_retransmit);
809 }
810 if (err != kDNSServiceErr_NoError) {
811 INFO("udp_retransmit: error %d setting wakeup", err);
812 // what to do?
813 }
814 }
815
816 static void
817 renew_callback(void *v_update_context)
818 {
819 update_context_t *context = v_update_context;
820 client_state_t *client = context->client;
821 INFO("renew callback");
822 do_srp_update(client, true);
823 }
824
825 // This function will, if hostname_rename_number is nonzero, create a hostname using the chosen hostname plus
826 // space plus the number as ascii text. The caller is responsible for freeing the return value if it's not NULL.
827 static char *
828 conflict_print(client_state_t *client, dns_towire_state_t *towire, char **return_hostname, char *chosen_hostname)
829 {
830 char *conflict_hostname;
831 size_t hostname_len;
832
833 if (client->hostname_rename_number == 0) {
834 *return_hostname = chosen_hostname;
835 return NULL;
836 }
837
838 hostname_len = strlen(chosen_hostname);
839 // 7 is max length of decimal short (5) plus space plus NUL
840 if (hostname_len + 7 > DNS_MAX_LABEL_SIZE) {
841 hostname_len = DNS_MAX_LABEL_SIZE - 7;
842 }
843 conflict_hostname = malloc(hostname_len + 7);
844 if (conflict_hostname == NULL) {
845 if (towire != NULL) {
846 towire->line = __LINE__;
847 towire->outer_line = -1;
848 towire->error = true;
849 }
850 *return_hostname = chosen_hostname;
851 return NULL;
852 }
853
854 memcpy(conflict_hostname, chosen_hostname, hostname_len);
855 snprintf(conflict_hostname + hostname_len, 7, " %d", client->hostname_rename_number);
856 *return_hostname = conflict_hostname;
857 return conflict_hostname;
858 }
859
860 static void
861 udp_response(void *v_update_context, void *v_message, size_t message_length)
862 {
863 update_context_t *context = v_update_context;
864 client_state_t *client = context->client;
865 dns_wire_t *message = v_message;
866 int err;
867 int rcode = dns_rcode_get(message);
868 (void)message_length;
869 uint32_t new_lease_time;
870 reg_state_t *registration;
871 const uint8_t *p = message->data;
872 const uint8_t *end = (const uint8_t *)v_message + message_length;
873 bool resolve_name_conflict = false;
874 char *conflict_hostname = NULL, *chosen_hostname;
875 uint32_t retry_time;
876
877 INFO("Got a response for %p, rcode = %d", client, dns_rcode_get(message));
878
879 // Cancel the retransmit wakeup.
880 err = srp_cancel_wakeup(client->os_context, context->udp_context);
881 if (err != kDNSServiceErr_NoError) {
882 INFO("udp_response: %d", err);
883 }
884 // We want a different UDP source port for each transaction, so cancel the current UDP state.
885 srp_disconnect_udp(context->udp_context);
886 context->connected = false;
887
888 // When we are doing a remove, we don't actually care what the result is--if we get back an answer, we call
889 // the callback.
890 if (context->removing) {
891 do_callbacks(client, context->serial, kDNSServiceErr_NoSuchRecord, false);
892 return;
893 }
894
895 // Deal with the response.
896 switch (rcode) {
897 case dns_rcode_noerror:
898 // Remember the server we connected with. active_update and active_update->server should always be
899 // non-NULL here.
900 if (client->active_update != NULL && client->active_update->server != NULL) {
901 // If the new server is not the one that's mentioned in stable_server, then update the one
902 // in stable_server.
903 if (client->active_update->server->rr.type != client->stable_server.rr.type ||
904 (client->stable_server.rr.type == dns_rrtype_a
905 ? memcmp(&client->stable_server.rr.data, &client->active_update->server->rr.data, 4)
906 : (client->stable_server.rr.type == dns_rrtype_aaaa
907 ? memcmp(&client->stable_server.rr.data, &client->active_update->server->rr.data, 16)
908 : true)) ||
909 memcmp(client->stable_server.port, client->active_update->server->port, 2))
910 {
911 memcpy(&client->stable_server, client->active_update->server, sizeof(client->stable_server));
912 client->srp_server_synced = false;
913 }
914 sync_to_stable_storage(client->active_update);
915 }
916
917 // Get the renewal time
918 // At present, there's no code to actually parse a real DNS packet in the client, so
919 // we rely on the server returning just an EDNS0 option; if this assumption fails, we
920 // are out of luck.
921 if (message->qdcount == 0 && message->ancount == 0 &&
922 message->nscount == 0 && ntohs(message->arcount) == 1 &&
923
924 // We expect the edns0 option to be:
925 // root label - 1 byte
926 // type = 2 bytes
927 // class = 2 bytes
928 // ttl = 4 bytes
929 // rdlength = 2 bytes
930 // lease option code = 2
931 // lease option length = 2
932 // lease = 4
933 // key lease = 4
934 // total = 23
935 end - p == 23 && // right number of bytes for an EDNS0 OPT containing an update lease option
936 *p == 0 && // root label
937 p[1] == (dns_rrtype_opt >> 8) && p[2] == (dns_rrtype_opt & 255) &&
938 // skip class and ttl, we don't care
939 p[9] == 0 && p[10] == 12 && // rdlength
940 p[11] == (dns_opt_update_lease >> 8) && p[12] == (dns_opt_update_lease & 255) &&
941 p[13] == 0 && p[14] == 8) // opt_length
942 {
943 new_lease_time = (((uint32_t)p[15] << 12) | ((uint32_t)p[16] << 8) |
944 ((uint32_t)p[17] << 8) | ((uint32_t)p[18]));
945 INFO("Lease time set to %" PRIu32, new_lease_time);
946 } else {
947 new_lease_time = context->lease_time;
948 INFO("Lease time defaults to %" PRIu32, new_lease_time);
949 DEBUG("len %ld qd %d an %d ns %d ar %d data %02x %02x %02x %02x %02x %02x %02x %02x %02x"
950 " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
951 (unsigned long)(end - p), ntohs(message->qdcount), ntohs(message->ancount),
952 ntohs(message->nscount), ntohs(message->arcount),
953 p[0], p[1], p[2], p[3], p[3], p[5], p[6], p[7], p[8], p[9], p[10], p[11],
954 p[12], p[13], p[14], p[15], p[16], p[17], p[18], p[19], p[20], p[21], p[22]);
955 }
956
957 // Set up to renew. Time is in milliseconds, and we want to renew at 80% of the lease time.
958 srp_set_wakeup(client->os_context, context->udp_context, (new_lease_time * 1000) * 8 / 10, renew_callback);
959
960 do_callbacks(client, context->serial, kDNSServiceErr_NoError, true);
961 break;
962 case dns_rcode_yxdomain:
963 // Get the actual hostname that we sent.
964 if (client->hostname_conflict_callback != NULL && client->hostname != NULL) {
965 conflict_hostname = conflict_print(client, NULL, &chosen_hostname, client->hostname);
966 client->hostname_conflict_callback(chosen_hostname);
967 if (conflict_hostname != NULL) {
968 free(conflict_hostname);
969 }
970 } else {
971 resolve_name_conflict = true;
972 }
973
974 bool resolve_with_callback = true;
975 for (registration = client->registrations; registration; registration = registration->next) {
976 if (registration->callback != NULL && registration->serial <= context->serial &&
977 !(registration->flags & kDNSServiceFlagsNoAutoRename))
978 {
979 resolve_with_callback = false;
980 }
981 }
982 if (resolve_with_callback) {
983 do_callbacks(client, context->serial, kDNSServiceErr_NameConflict, false);
984 } else {
985 resolve_name_conflict = true;
986 }
987
988 if (resolve_name_conflict) {
989 // If we get a name conflict, try using a low number to rename, but only twice; it's time consuming to do
990 // this, so if we get two conflicts, we switch to using a random number.
991 if (client->hostname_rename_number < 2) {
992 client->hostname_rename_number++;
993 } else {
994 client->hostname_rename_number = srp_random16();
995 }
996 // When we get a name conflict response, we need to re-do the update immediately
997 // (with a 0-500ms delay of course).
998 do_srp_update(client, true);
999 }
1000 break;
1001
1002 default:
1003 // Any other response has to be treated as a transient failure, so we need to retry
1004 // This sort of failure is essentially unacceptable in a real deployment--it indicates
1005 // that something is seriously broken. But it's not up to the client to debug that.
1006 retry_time = context->lease_time * 4 / 5;
1007 // We don't want to retry _too_ often.
1008 if (retry_time < 120) {
1009 retry_time = 120;
1010 }
1011 srp_set_wakeup(client->os_context, context->udp_context, retry_time * 1000, renew_callback);
1012 break;
1013 }
1014 }
1015
1016 // Generate a new SRP update message
1017 static dns_wire_t *
1018 generate_srp_update(client_state_t *client, uint32_t update_lease_time, uint32_t update_key_lease_time,
1019 size_t *NONNULL p_length, service_addr_t *server, uint32_t serial, bool removing)
1020 {
1021 dns_wire_t *message;
1022 const char *zone_name = "default.service.arpa";
1023 const char *service_type = "_ipps._tcp";
1024 const char *txt_record = "0";
1025 uint16_t key_tag;
1026 dns_towire_state_t towire;
1027 dns_name_pointer_t p_host_name;
1028 dns_name_pointer_t p_zone_name;
1029 dns_name_pointer_t p_service_name;
1030 dns_name_pointer_t p_service_instance_name;
1031 int line, pass;
1032 service_addr_t *addr;
1033 reg_state_t *reg;
1034 char *conflict_hostname = NULL, *chosen_hostname;
1035
1036 #define INCREMENT(x) (x) = htons(ntohs(x) + 1)
1037 memset(&towire, 0, sizeof towire);
1038
1039 // Get the key if we don't already have it.
1040 if (client->key == NULL) {
1041 client->key = srp_get_key("com.apple.srp-client.host-key", client->os_context);
1042 if (client->key == NULL) {
1043 INFO("No key gotten.");
1044 return NULL;
1045 }
1046 }
1047
1048 #define CH if (towire.error) { line = __LINE__; goto fail; }
1049
1050 if (client->hostname == NULL) {
1051 ERROR("generate_srp_update called with NULL hostname.");
1052 return NULL;
1053 }
1054
1055 // Allocate a message buffer.
1056 message = calloc(1, sizeof *message);
1057 if (message == NULL) {
1058 return NULL;
1059 }
1060 towire.p = &message->data[0]; // We start storing RR data here.
1061 towire.lim = &message->data[DNS_DATA_SIZE]; // This is the limit to how much we can store.
1062 towire.message = message;
1063
1064 // Generate a random UUID.
1065 message->id = srp_random16();
1066 message->bitfield = 0;
1067 dns_qr_set(message, dns_qr_query);
1068 dns_opcode_set(message, dns_opcode_update);
1069
1070 message->qdcount = 0;
1071 // Copy in Zone name (and save pointer)
1072 // ZTYPE = SOA
1073 // ZCLASS = IN
1074 dns_full_name_to_wire(&p_zone_name, &towire, zone_name); CH;
1075 dns_u16_to_wire(&towire, dns_rrtype_soa); CH;
1076 dns_u16_to_wire(&towire, dns_qclass_in); CH;
1077 INCREMENT(message->qdcount);
1078
1079 message->ancount = 0;
1080 // PRCOUNT = 0
1081
1082 message->nscount = 0;
1083 // UPCOUNT = ...
1084
1085 // Host Description:
1086 // * Delete all RRsets from <hostname>; remember the pointer to hostname
1087 // NAME = hostname label followed by pointer to SOA name.
1088 // TYPE = ANY
1089 // CLASS = ANY
1090 // TTL = 0
1091 // RDLENGTH = 0
1092
1093 conflict_hostname = conflict_print(client, &towire, &chosen_hostname, client->hostname); CH;
1094 dns_name_to_wire(&p_host_name, &towire, chosen_hostname); CH;
1095 dns_pointer_to_wire(&p_host_name, &towire, &p_zone_name); CH;
1096 dns_u16_to_wire(&towire, dns_rrtype_any); CH;
1097 dns_u16_to_wire(&towire, dns_qclass_any); CH;
1098 dns_ttl_to_wire(&towire, 0); CH;
1099 dns_u16_to_wire(&towire, 0); CH;
1100 INCREMENT(message->nscount);
1101
1102 // * Add addresses: A and/or AAAA RRsets, each of which contains one
1103 // or more A or AAAA RRs.
1104 // NAME = pointer to hostname from Delete (above)
1105 // TYPE = A or AAAA
1106 // CLASS = IN
1107 // TTL = 3600 ?
1108 // RDLENGTH = number of RRs * RR length (4 or 16)
1109 // RDATA = <the data>
1110 for (pass = 0; pass < 2; pass++) {
1111 bool have_good_address = false;
1112
1113 for (addr = interfaces; addr; addr = addr->next) {
1114 // If we have an IPv6 address that's on the same prefix as the server's address, send only that
1115 // IPv6 address.
1116 if (addr->rr.type != dns_rrtype_aaaa ||
1117 (addr->rr.type == server->rr.type && !memcmp(&addr->rr.data, &server->rr.data, 8)))
1118 {
1119 have_good_address = true;
1120 }
1121 if (have_good_address || pass == 1) {
1122 dns_pointer_to_wire(NULL, &towire, &p_host_name); CH;
1123 dns_u16_to_wire(&towire, addr->rr.type); CH;
1124 dns_u16_to_wire(&towire, dns_qclass_in); CH;
1125 dns_ttl_to_wire(&towire, 3600); CH;
1126 dns_rdlength_begin(&towire); CH;
1127 dns_rdata_raw_data_to_wire(&towire, &addr->rr.data,
1128 addr->rr.type == dns_rrtype_a ? 4 : 16); CH;
1129 dns_rdlength_end(&towire); CH;
1130 INCREMENT(message->nscount);
1131 }
1132 if (have_good_address) {
1133 break;
1134 }
1135 }
1136 }
1137
1138 // * Exactly one KEY RR:
1139 // NAME = pointer to hostname from Delete (above)
1140 // TYPE = KEY
1141 // CLASS = IN
1142 // TTL = 3600
1143 // RDLENGTH = length of key + 4 (32 bits)
1144 // RDATA = <flags(16) = 0000 0010 0000 0001, protocol(8) = 3, algorithm(8) = 8?, public key(variable)>
1145 dns_pointer_to_wire(NULL, &towire, &p_host_name); CH;
1146 dns_u16_to_wire(&towire, dns_rrtype_key); CH;
1147 dns_u16_to_wire(&towire, dns_qclass_in); CH;
1148 dns_ttl_to_wire(&towire, 3600); CH;
1149 dns_rdlength_begin(&towire); CH;
1150 key_tag = dns_rdata_key_to_wire(&towire, 0, 2, 1, client->key); CH;
1151 dns_rdlength_end(&towire); CH;
1152 INCREMENT(message->nscount);
1153
1154 // Emit any registrations.
1155 for (reg = client->registrations; reg; reg = reg->next) {
1156 // Only remove the registrations that are actually registered. Normally this will be all of them, but it's
1157 // possible for a registration to be added but not to have been updated yet, and then for us to get a remove
1158 // call, in which case we don't need to remove it.
1159 if (removing && reg->serial > serial) {
1160 continue;
1161 }
1162
1163 // Service:
1164 // * Update PTR RR
1165 // NAME = service name (_a._b.service.arpa)
1166 // TYPE = PTR
1167 // CLASS = IN
1168 // TTL = 3600
1169 // RDLENGTH = 2
1170 // RDATA = service instance name
1171 dns_name_to_wire(&p_service_name, &towire, reg->regtype == NULL ? service_type : reg->regtype); CH;
1172 dns_pointer_to_wire(&p_service_name, &towire, &p_zone_name); CH;
1173 dns_u16_to_wire(&towire, dns_rrtype_ptr); CH;
1174 dns_u16_to_wire(&towire, dns_qclass_in); CH;
1175 dns_ttl_to_wire(&towire, 3600); CH;
1176 dns_rdlength_begin(&towire); CH;
1177 if (reg->name != NULL) {
1178 char *service_instance_name, *to_free = conflict_print(client, &towire, &service_instance_name, reg->name);
1179 dns_name_to_wire(&p_service_instance_name, &towire, service_instance_name); CH;
1180 if (to_free != NULL) {
1181 free(to_free);
1182 }
1183 } else {
1184 dns_name_to_wire(&p_service_instance_name, &towire, chosen_hostname); CH;
1185 }
1186 dns_pointer_to_wire(&p_service_instance_name, &towire, &p_service_name); CH;
1187 dns_rdlength_end(&towire); CH;
1188 INCREMENT(message->nscount);
1189
1190 // Service Instance:
1191 // * Delete all RRsets from service instance name
1192 // NAME = service instance name (save pointer to service name, which is the second label)
1193 // TYPE = ANY
1194 // CLASS = ANY
1195 // TTL = 0
1196 // RDLENGTH = 0
1197 dns_pointer_to_wire(NULL, &towire, &p_service_instance_name); CH;
1198 dns_u16_to_wire(&towire, dns_rrtype_any); CH;
1199 dns_u16_to_wire(&towire, dns_qclass_any); CH;
1200 dns_ttl_to_wire(&towire, 0); CH;
1201 dns_u16_to_wire(&towire, 0); CH;
1202 INCREMENT(message->nscount);
1203
1204 // * Add one SRV RRset pointing to Host Description
1205 // NAME = pointer to service instance name from above
1206 // TYPE = SRV
1207 // CLASS = IN
1208 // TTL = 3600
1209 // RDLENGTH = 8
1210 // RDATA = <priority(16) = 0, weight(16) = 0, port(16) = service port, target = pointer to hostname>
1211 dns_pointer_to_wire(NULL, &towire, &p_service_instance_name); CH;
1212 dns_u16_to_wire(&towire, dns_rrtype_srv); CH;
1213 dns_u16_to_wire(&towire, dns_qclass_in); CH;
1214 dns_ttl_to_wire(&towire, 3600); CH;
1215 dns_rdlength_begin(&towire); CH;
1216 dns_u16_to_wire(&towire, 0); CH; // priority
1217 dns_u16_to_wire(&towire, 0); CH; // weight
1218 dns_u16_to_wire(&towire, reg->port); CH; // port
1219 dns_pointer_to_wire(NULL, &towire, &p_host_name); CH;
1220 dns_rdlength_end(&towire); CH;
1221 INCREMENT(message->nscount);
1222
1223 // * Add one or more TXT records
1224 // NAME = pointer to service instance name from above
1225 // TYPE = TXT
1226 // CLASS = IN
1227 // TTL = 3600
1228 // RDLENGTH = <length of text>
1229 // RDATA = <text>
1230 dns_pointer_to_wire(NULL, &towire, &p_service_instance_name); CH;
1231 dns_u16_to_wire(&towire, dns_rrtype_txt); CH;
1232 dns_u16_to_wire(&towire, dns_qclass_in); CH;
1233 dns_ttl_to_wire(&towire, 3600); CH;
1234 dns_rdlength_begin(&towire); CH;
1235 if (reg->txtRecord != NULL) {
1236 dns_rdata_raw_data_to_wire(&towire, reg->txtRecord, reg->txtLen);
1237 } else {
1238 dns_rdata_txt_to_wire(&towire, txt_record); CH;
1239 }
1240 dns_rdlength_end(&towire); CH;
1241 INCREMENT(message->nscount);
1242 }
1243
1244 // What about services with more than one name? Are these multiple service descriptions?
1245
1246 // ARCOUNT = 2
1247 // EDNS(0) options
1248 // ...
1249 // SIG(0)
1250
1251 message->arcount = 0;
1252 dns_edns0_header_to_wire(&towire, DNS_MAX_UDP_PAYLOAD, 0, 0, 1); CH; // XRCODE = 0; VERSION = 0; DO=1
1253 dns_rdlength_begin(&towire); CH;
1254 dns_u16_to_wire(&towire, dns_opt_update_lease); CH; // OPTION-CODE
1255 dns_edns0_option_begin(&towire); CH; // OPTION-LENGTH
1256 if (removing) {
1257 // If we are removing the record, lease time should be zero. Key_lease_time can be nonzero, but we
1258 // aren't currently offering a way to do that.
1259 dns_u32_to_wire(&towire, 0); CH;
1260 dns_u32_to_wire(&towire, 0); CH;
1261 } else {
1262 dns_u32_to_wire(&towire, update_lease_time); CH; // LEASE (e.g. 1 hour)
1263 dns_u32_to_wire(&towire, update_key_lease_time); CH; // KEY-LEASE (7 days)
1264 }
1265 dns_edns0_option_end(&towire); CH; // Now we know OPTION-LENGTH
1266 dns_rdlength_end(&towire); CH;
1267 INCREMENT(message->arcount);
1268
1269 // The signature must be computed before counting the signature RR in the header counts.
1270 dns_sig0_signature_to_wire(&towire, client->key, key_tag, &p_host_name, chosen_hostname, zone_name); CH;
1271 INCREMENT(message->arcount);
1272 *p_length = towire.p - (uint8_t *)message;
1273
1274 if (conflict_hostname != NULL) {
1275 free(conflict_hostname);
1276 }
1277 return message;
1278
1279 fail:
1280 if (conflict_hostname != NULL) {
1281 free(conflict_hostname);
1282 }
1283
1284 if (towire.error) {
1285 ERROR("Ran out of message space at srp-client.c:%d (%d, %d)",
1286 line, towire.line, towire.outer_line);
1287 }
1288 if (client->active_update != NULL) {
1289 update_finalize(client->active_update);
1290 client->active_update = NULL;
1291 }
1292 if (message != NULL) {
1293 free(message);
1294 }
1295 return NULL;
1296 }
1297
1298 // Send SRP updates for host records that have changed.
1299 static int
1300 do_srp_update(client_state_t *client, bool definite)
1301 {
1302 int err;
1303 service_addr_t *server;
1304 service_addr_t *interface, *registered;
1305
1306 // Cancel any ongoing active update.
1307 if (!definite && client->active_update != NULL) {
1308 bool server_changed = true;
1309 bool interface_changed = false;
1310 for (server = servers; server != NULL; server = server->next) {
1311 if (server == client->active_update->server) {
1312 server_changed = false;
1313 }
1314 }
1315 for (registered = client->active_update->interfaces; registered != NULL; registered = registered->next) {
1316 for (interface = interfaces; interface; interface = interface->next) {
1317 if (interface == registered) {
1318 break;
1319 }
1320 }
1321 if (interface == NULL) {
1322 interface_changed = true;
1323 break;
1324 }
1325 }
1326 if (!interface_changed && !server_changed) {
1327 INFO("do_srp_update: addresses to register are the same; server is the same.");
1328 return kDNSServiceErr_NoError;
1329 }
1330 }
1331
1332 // Get rid of the previous update, if any.
1333 if (client->active_update != NULL) {
1334 update_finalize(client->active_update);
1335 client->active_update = NULL;
1336 }
1337
1338 // Make an update context.
1339 update_context_t *active_update = calloc(1, sizeof(*active_update));
1340 if (active_update == NULL) {
1341 err = kDNSServiceErr_NoMemory;
1342 } else {
1343 // If possible, use the server we used last time.
1344 active_update->client = client;
1345 sync_from_stable_storage(active_update);
1346 if (active_update->server == NULL) {
1347 active_update->server = servers;
1348 }
1349 active_update->serial = client->registration_serial;
1350 active_update->message = NULL;
1351 active_update->message_length = 0;
1352 // If the initial transmission times out, start retrying at ~two seconds.
1353 active_update->next_retransmission_time = 2000;
1354 // If this update times out, try again in two minutes, backing off to an hour exponentially.
1355 active_update->next_attempt_time = 1000 * 2 * 60;
1356 active_update->lease_time = client->lease_time;
1357 active_update->key_lease_time = client->key_lease_time;
1358 active_update->interfaces = calloc(1, sizeof(*active_update->interfaces));
1359 if (active_update->interfaces == NULL) {
1360 err = kDNSServiceErr_NoMemory;
1361 INFO("No memory for interface address");
1362 } else {
1363 memcpy(active_update->interfaces, interfaces, sizeof(*interfaces));
1364 err = srp_make_udp_context(client->os_context, &active_update->udp_context, udp_response, active_update);
1365 }
1366 }
1367 if (err == kDNSServiceErr_NoError) {
1368 // XXX use some random jitter on these times.
1369 active_update->next_retransmission_time = 2000;
1370 err = srp_set_wakeup(client->os_context, active_update->udp_context, srp_random16() % 1023, udp_retransmit);
1371 }
1372 if (err != kDNSServiceErr_NoError) {
1373 if (active_update != NULL) {
1374 update_finalize(active_update);
1375 active_update = NULL;
1376 }
1377 }
1378 client->active_update = active_update;
1379 return err;
1380 }
1381
1382 // Deregister all existing registrations.
1383 int
1384 srp_deregister(void *os_context)
1385 {
1386 reg_state_t *rp;
1387 bool something_to_deregister = false;
1388 client_state_t *client;
1389
1390 for (client = clients; client; client = client->next) {
1391 if (client->os_context == os_context) {
1392 break;
1393 }
1394 }
1395 if (client == NULL) {
1396 return kDNSServiceErr_Invalid;
1397 }
1398
1399 if (client->active_update == NULL) {
1400 INFO("srp_deregister: no active update.");
1401 return kDNSServiceErr_NoSuchRecord;
1402 }
1403
1404 // See if there are any registrations that have succeeded.
1405 for (rp = client->registrations; rp; rp = rp->next) {
1406 if (rp->serial <= client->active_update->serial && rp->succeeded) {
1407 something_to_deregister = true;
1408 }
1409 }
1410
1411 // If so, start a deregistration update; otherwise return NoSuchRecord.
1412 if (something_to_deregister) {
1413 if (client->active_update->message) {
1414 free(client->active_update->message);
1415 client->active_update->message = NULL;
1416 }
1417 client->active_update->removing = true;
1418 client->active_update->next_retransmission_time = 2000;
1419 client->active_update->next_attempt_time = 1000 * 2 * 60;
1420 udp_retransmit(client->active_update);
1421 return kDNSServiceErr_NoError;
1422 } else {
1423 return kDNSServiceErr_NoSuchRecord;
1424 }
1425 }
1426
1427 // Local Variables:
1428 // mode: C
1429 // tab-width: 4
1430 // c-file-style: "bsd"
1431 // c-basic-offset: 4
1432 // fill-column: 108
1433 // indent-tabs-mode: nil
1434 // End: