]> git.saurik.com Git - apple/mdnsresponder.git/blob - ServiceRegistration/srp-thread.c
mDNSResponder-1310.40.42.tar.gz
[apple/mdnsresponder.git] / ServiceRegistration / srp-thread.c
1 /* srp-thread.c
2 *
3 * Copyright (c) 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 host API implementation for Thread accessories using OpenThread.
18 */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <fcntl.h>
26
27 #include <openthread/ip6.h>
28 #include <openthread/instance.h>
29 #include <openthread/thread.h>
30 #include <openthread/joiner.h>
31 #include <openthread/message.h>
32 #include <openthread/udp.h>
33 #include <openthread/platform/time.h>
34 #include <openthread/platform/settings.h>
35
36
37 #include "app_scheduler.h"
38 #include "app_timer.h"
39 #include "srp.h"
40 #include "srp-thread.h"
41 #include "srp-api.h"
42 #include "dns_sd.h"
43 #include "HAPPlatformRandomNumber.h"
44 #include "dns-msg.h"
45 #include "dns_sd.h"
46 #define SRP_CRYPTO_MBEDTLS_INTERNAL 1
47 #include "srp-crypto.h"
48
49 APP_TIMER_DEF(m_srp_timer);
50 #define HAPTIME_FREQUENCY 1000ULL
51
52 const char *key_filename = "srp.key";
53
54 #define SRP_IO_CONTEXT_MAGIC 0xFEEDFACEFADEBEEFULL // BEES! Everybody gets BEES!
55 typedef struct io_context io_context_t;
56
57 struct io_context {
58 uint64_t magic_cookie1;
59 io_context_t *next;
60 HAPTime wakeup_time;
61 void *NONNULL srp_context;
62 otSockAddr sockaddr;
63 otUdpSocket sock;
64 srp_wakeup_callback_t wakeup_callback;
65 srp_datagram_callback_t datagram_callback;
66 bool sock_active;
67 uint64_t magic_cookie2;
68 } *io_contexts;
69
70 static otInstance *otThreadInstance;
71
72 static int
73 validate_io_context(io_context_t **dest, void *src)
74 {
75 io_context_t *context = src;
76 if (context->magic_cookie1 == SRP_IO_CONTEXT_MAGIC &&
77 context->magic_cookie2 == SRP_IO_CONTEXT_MAGIC)
78 {
79 *dest = context;
80 return kDNSServiceErr_NoError;
81 }
82 return kDNSServiceErr_BadState;
83 }
84
85 void
86 datagram_callback(void *context, otMessage *message, const otMessageInfo *messageInfo)
87 {
88 static uint8_t *buf;
89 const int buf_len = 1500;
90 int length;
91 io_context_t *io_context;
92 if (validate_io_context(&io_context, context) == kDNSServiceErr_NoError) {
93 if (buf == NULL) {
94 buf = malloc(buf_len);
95 if (buf == NULL) {
96 INFO("No memory for read buffer");
97 return;
98 }
99 }
100
101 DEBUG("%d bytes received", otMessageGetLength(message) - otMessageGetOffset(message));
102 length = otMessageRead(message, otMessageGetOffset(message), buf, buf_len - 1);
103 io_context->datagram_callback(io_context->srp_context, buf, length);
104 }
105 }
106
107 static void wakeup_callback(void *context);
108
109 static void
110 note_wakeup(const char *what, void *at, uint64_t when)
111 {
112 #ifdef VERBOSE_DEBUG_MESSAGES
113 int microseconds = (int)(when % HAPTIME_FREQUENCY);
114 HAPTime seconds = when / HAPTIME_FREQUENCY;
115 int minute = (int)((seconds / 60) % 60);
116 int hour = (int)((seconds / 3600) % (7 * 24));
117 int second = (int)(seconds % 60);
118
119 DEBUG(PUB_S_SRP " %p at %llu %d:%d:%d.%d", what, at, when, hour, minute, second, microseconds);
120 #endif
121 }
122
123 static void
124 compute_wakeup_time(HAPTime now)
125 {
126 io_context_t *io_context;
127 HAPTime next = 0;
128 uint32_t err;
129
130 for (io_context = io_contexts; io_context; io_context = io_context->next) {
131 if (next == 0 || (io_context->wakeup_time != 0 && io_context->wakeup_time < next)) {
132 next = io_context->wakeup_time;
133 }
134 }
135
136 // If we don't have a wakeup to schedule, wake up anyway in ten seconds.
137 if (next == 0) {
138 next = now + 10 * HAPTIME_FREQUENCY;
139 }
140 note_wakeup("next wakeup", NULL, next);
141 if (next != 0) {
142 int milliseconds;
143 if (next <= now) {
144 milliseconds = 1;
145 } else {
146 milliseconds = (int)((next - now) / (HAPTIME_FREQUENCY / 1000));
147 }
148 err = app_timer_start(m_srp_timer, APP_TIMER_TICKS(milliseconds), NULL);
149 if (err != 0) {
150 ERROR("app_timer_start returned %lu", err);
151 }
152 }
153 }
154
155 static void
156 wakeup_callback(void *context)
157 {
158 io_context_t *io_context;
159 HAPTime now = HAPPlatformClockGetCurrent(), next = 0;
160 bool more;
161
162 note_wakeup(" wakeup", NULL, now);
163 do {
164 more = false;
165 for (io_context = io_contexts; io_context; io_context = io_context->next) {
166 if (io_context->wakeup_time != 0 && io_context->wakeup_time < now) {
167 more = true;
168 note_wakeup("io wakeup", io_context, io_context->wakeup_time);
169 io_context->wakeup_time = 0;
170 io_context->wakeup_callback(io_context->srp_context);
171 break;
172 }
173 note_wakeup("no wakeup", io_context, io_context->wakeup_time);
174 if (next == 0 || (io_context->wakeup_time != 0 && io_context->wakeup_time < next))
175 {
176 next = io_context->wakeup_time;
177 }
178 }
179 } while (more);
180 compute_wakeup_time(now);
181 }
182
183 int
184 srp_deactivate_udp_context(void *host_context, void *in_context)
185 {
186 io_context_t *io_context, **p_io_contexts;
187 int err;
188
189 err = validate_io_context(&io_context, in_context);
190 if (err == kDNSServiceErr_NoError) {
191 for (p_io_contexts = &io_contexts; *p_io_contexts; p_io_contexts = &(*p_io_contexts)->next) {
192 if (*p_io_contexts == io_context) {
193 break;
194 }
195 }
196 // If we don't find it on the list, something is wrong.
197 if (*p_io_contexts == NULL) {
198 return kDNSServiceErr_Invalid;
199 }
200 *p_io_contexts = io_context->next;
201 io_context->wakeup_time = 0;
202 if (io_context->sock_active) {
203 otUdpClose(&io_context->sock);
204 }
205 free(io_context);
206 }
207 return err;
208 }
209
210 int
211 srp_connect_udp(void *context, const uint8_t *port, uint16_t address_type, const uint8_t *address, uint16_t addrlen)
212 {
213 io_context_t *io_context;
214 int err, oterr;
215
216 err = validate_io_context(&io_context, context);
217
218 if (err == kDNSServiceErr_NoError) {
219 if (address_type != dns_rrtype_aaaa || addrlen != 16) {
220 ERROR("srp_make_udp_context: invalid address");
221 return kDNSServiceErr_Invalid;
222 }
223 memcpy(&io_context->sockaddr.mAddress, address, 16);
224 memcpy(&io_context->sockaddr.mPort, port, 2);
225 #ifdef OT_NETIF_INTERFACE_ID_THREAD
226 io_context->sockaddr.mScopeId = OT_NETIF_INTERFACE_ID_THREAD;
227 #endif
228
229 oterr = otUdpOpen(otThreadInstance, &io_context->sock, datagram_callback, io_context);
230 if (oterr != OT_ERROR_NONE) {
231 ERROR("srp_make_udp_context: otUdpOpen returned %d", oterr);
232 return kDNSServiceErr_Unknown;
233 }
234
235 oterr = otUdpConnect(&io_context->sock, &io_context->sockaddr);
236 if (oterr != OT_ERROR_NONE) {
237 otUdpClose(&io_context->sock);
238 ERROR("srp_make_udp_context: otUdpConnect returned %d", oterr);
239 return kDNSServiceErr_Unknown;
240 }
241 io_context->sock_active = true;
242 err = kDNSServiceErr_NoError;
243 }
244 return err;
245 }
246
247 int
248 srp_disconnect_udp(void *context)
249 {
250 io_context_t *io_context;
251 int err;
252
253 err = validate_io_context(&io_context, context);
254 if (err == kDNSServiceErr_NoError && io_context->sock_active) {
255 otUdpClose(&io_context->sock);
256 io_context->sock_active = false;
257 }
258 return err;
259 }
260
261 int
262 srp_make_udp_context(void *host_context, void **p_context, srp_datagram_callback_t callback, void *context)
263 {
264 io_context_t *io_context = calloc(1, sizeof *io_context);
265 if (io_context == NULL) {
266 ERROR("srp_make_udp_context: no memory");
267 return kDNSServiceErr_NoMemory;
268 }
269 io_context->magic_cookie1 = io_context->magic_cookie2 = SRP_IO_CONTEXT_MAGIC;
270 io_context->datagram_callback = callback;
271 io_context->srp_context = context;
272
273 *p_context = io_context;
274 io_context->next = io_contexts;
275 io_contexts = io_context;
276 return kDNSServiceErr_NoError;
277 }
278
279 int
280 srp_set_wakeup(void *host_context, void *context, int milliseconds, srp_wakeup_callback_t callback)
281 {
282 int err;
283 io_context_t *io_context;
284 HAPTime now;
285
286 err = validate_io_context(&io_context, context);
287 if (err == kDNSServiceErr_NoError) {
288 now = HAPPlatformClockGetCurrent();
289 io_context->wakeup_time = now + milliseconds * (HAPTIME_FREQUENCY / 1000);
290 io_context->wakeup_callback = callback;
291 INFO("srp_set_wakeup: %llu (%llu + %dms)", io_context->wakeup_time, now, milliseconds);
292 compute_wakeup_time(now);
293 }
294 return err;
295 }
296
297 int
298 srp_cancel_wakeup(void *host_context, void *context)
299 {
300 int err;
301 io_context_t *io_context;
302
303 err = validate_io_context(&io_context, context);
304 if (err == kDNSServiceErr_NoError) {
305 io_context->wakeup_time = 0;
306 }
307 return err;
308 }
309
310 int
311 srp_send_datagram(void *host_context, void *context, void *payload, size_t message_length)
312 {
313 int err;
314 io_context_t *io_context;
315 otError error;
316 otMessageInfo messageInfo;
317 otMessage * message = NULL;
318 uint8_t *ap;
319
320 #ifdef VERBOSE_DEBUG_MESSAGES
321 int i, j;
322 char buf[80], *bufp;
323 char *hexdigits = "01234567689abcdef";
324 uint8_t *msg = payload;
325 #endif // VERBOSE_DEBUG_MESSAGES
326
327 err = validate_io_context(&io_context, context);
328 if (err == kDNSServiceErr_NoError) {
329 memset(&messageInfo, 0, sizeof(messageInfo));
330 #ifdef OT_NETIF_INTERFACE_ID_THREAD
331 messageInfo.mInterfaceId = OT_NETIF_INTERFACE_ID_THREAD;
332 #endif
333 messageInfo.mPeerPort = io_context->sockaddr.mPort;
334 messageInfo.mPeerAddr = io_context->sockaddr.mAddress;
335 ap = (uint8_t *)&io_context->sockaddr.mAddress;
336 SEGMENTED_IPv6_ADDR_GEN_SRP(ap, ap_buf);
337 INFO("Sending to " PRI_SEGMENTED_IPv6_ADDR_SRP " port %d", SEGMENTED_IPv6_ADDR_PARAM_SRP(ap, ap_buf),
338 io_context->sockaddr.mPort);
339 #ifdef VERBOSE_DEBUG_MESSAGES
340 for (i = 0; i < message_length; i += 32) {
341 bufp = buf;
342 for (j = 0; bufp < buf + sizeof buf && i + j < message_length; j++) {
343 *bufp++ = hexdigits[msg[i + j] >> 4];
344 if (bufp < buf + sizeof buf) {
345 *bufp++ = hexdigits[msg[i + j] % 15];
346 }
347 if (bufp < buf + sizeof buf && (j & 1) == 1) {
348 *bufp++ = ' ';
349 }
350 }
351 *bufp = 0;
352 DEBUG(PUB_S_SRP, buf);
353 }
354 #endif
355
356 message = otUdpNewMessage(otThreadInstance, NULL);
357 if (message == NULL) {
358 ERROR("srp_send_datagram: otUdpNewMessage returned NULL");
359 return kDNSServiceErr_NoMemory;
360 }
361
362 error = otMessageAppend(message, payload, message_length);
363 if (error != OT_ERROR_NONE) {
364 ERROR("srp_send_datagram: otMessageAppend returned %d", error);
365 return kDNSServiceErr_NoMemory;
366 }
367
368 error = otUdpSend(&io_context->sock, message, &messageInfo);
369 if (error != OT_ERROR_NONE) {
370 ERROR("srp_send_datagram: otUdpSend returned %d", error);
371 return kDNSServiceErr_Unknown;
372 }
373 }
374 return err;
375 }
376
377 #define KEY_ID 1000
378 int
379 srp_load_key_data(void *host_context, const char *key_name,
380 uint8_t *buffer, uint16_t *length, uint16_t buffer_size)
381 {
382 #ifndef DEBUG_CONFLICTS
383 otError err;
384 uint16_t rlength = buffer_size;
385 // Note that at present we ignore the key name: we are only going to have one host key on an
386 // accessory.
387 err = otPlatSettingsGet(otThreadInstance, KEY_ID, 0, buffer, &rlength);
388 if (err != OT_ERROR_NONE) {
389 *length = 0;
390 return kDNSServiceErr_NoSuchKey;
391 }
392 *length = rlength;
393 return kDNSServiceErr_NoError;
394 #else
395 return kDNSServiceErr_NoSuchKey;
396 #endif
397 }
398
399 int
400 srp_store_key_data(void *host_context, const char *name, uint8_t *buffer, uint16_t length)
401 {
402 otError err;
403 err = otPlatSettingsAdd(otThreadInstance, KEY_ID, buffer, length);
404 if (err != OT_ERROR_NONE) {
405 ERROR("Unable to store key (length %d): %d", length, err);
406 return kDNSServiceErr_Unknown;
407 }
408 return kDNSServiceErr_NoError;
409 }
410
411 int
412 srp_reset_key(const char *name, void *host_context)
413 {
414 otPlatSettingsDelete(otThreadInstance, KEY_ID);
415 }
416
417 void
418 register_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
419 const char *name, const char *regtype, const char *domain, void *context)
420 {
421 INFO("Register Reply: %ld " PRI_S_SRP " " PRI_S_SRP " " PRI_S_SRP "\n", errorCode, name == NULL ? "<NULL>" : name,
422 regtype == NULL ? "<NULL>" : regtype, domain == NULL ? "<NULL>" : domain);
423 }
424
425 void
426 conflict_callback(const char *hostname)
427 {
428 ERROR("Host name conflict: %s", hostname);
429 }
430
431 int
432 srp_thread_init(otInstance *instance)
433 {
434 uint32_t app_err;
435 DEBUG("In srp_thread_init().");
436 otThreadInstance = instance;
437 srp_host_init(otThreadInstance);
438
439 app_err = app_timer_create(&m_srp_timer, APP_TIMER_MODE_SINGLE_SHOT, wakeup_callback);
440 if (app_err != 0) {
441 ERROR("app_timer_create returned %lu", app_err);
442 return kDNSServiceErr_Unknown;
443 }
444 return kDNSServiceErr_NoError;
445 }
446
447 int
448 srp_thread_shutdown(otInstance *instance)
449 {
450 INFO("In srp_thread_shutdown().");
451 uint32_t app_err;
452 app_err = app_timer_stop(m_srp_timer);
453 if (app_err != 0) {
454 ERROR("app_timer_stop returned %lu", app_err);
455 return kDNSServiceErr_Unknown;
456 }
457 return kDNSServiceErr_NoError;
458 }
459
460 // Local Variables:
461 // mode: C
462 // tab-width: 4
463 // c-file-style: "bsd"
464 // c-basic-offset: 4
465 // fill-column: 108
466 // indent-tabs-mode: nil
467 // End: