source: rtems-libbsd/mDNSResponder/mDNSMacOSX/DNSServiceDiscovery.c @ f761b29

55-freebsd-126-freebsd-12
Last change on this file since f761b29 was f761b29, checked in by Sebastian Huber <sebastian.huber@…>, on 09/19/18 at 06:52:21

mDNSResponder: Update to v625.41.2

The sources can be obtained via:

https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-625.41.2.tar.gz

Update #3522.

  • Property mode set to 100644
File size: 19.5 KB
Line 
1/* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2002-2012 Apple 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
18// Suppress "warning: 'DNSServiceDiscoveryMachPort' is deprecated" messages -- we already know this code is building the deprecated API
19// Since we compile with all warnings treated as errors, we have to turn off the warnings here or the project won't compile
20#include <AvailabilityMacros.h>
21#undef AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED
22#define AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED
23#undef AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3
24#define AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3
25
26#include "../mDNSMacOSX/DNSServiceDiscovery.h"
27#include "DNSServiceDiscoveryDefines.h"
28#include "DNSServiceDiscoveryReplyServer.h"
29
30#include <stdlib.h>
31#include <stdio.h>
32#include <servers/bootstrap.h>
33#include <mach/mach.h>
34#include <mach/mach_error.h>
35#include <pthread.h>
36
37#include <netinet/in.h>
38
39extern boolean_t DNSServiceDiscoveryReply_server(
40    mach_msg_header_t *InHeadP,
41    mach_msg_header_t *OutHeadP);
42
43extern
44kern_return_t DNSServiceBrowserCreate_rpc
45(
46    mach_port_t server,
47    mach_port_t client,
48    DNSCString regtype,
49    DNSCString domain
50);
51
52extern
53kern_return_t DNSServiceDomainEnumerationCreate_rpc
54(
55    mach_port_t server,
56    mach_port_t client,
57    int registrationDomains
58);
59
60extern
61kern_return_t DNSServiceRegistrationCreate_rpc
62(
63    mach_port_t server,
64    mach_port_t client,
65    DNSCString name,
66    DNSCString regtype,
67    DNSCString domain,
68    IPPort port,
69    DNSCString txtRecord
70);
71
72extern
73kern_return_t DNSServiceResolverResolve_rpc
74(
75    mach_port_t server,
76    mach_port_t client,
77    DNSCString name,
78    DNSCString regtype,
79    DNSCString domain
80);
81
82extern
83kern_return_t DNSServiceRegistrationAddRecord_rpc
84(
85    mach_port_t server,
86    mach_port_t client,
87    int type,
88    record_data_t data,
89    mach_msg_type_number_t record_dataCnt,
90    uint32_t ttl,
91    natural_t *reference
92);
93
94extern
95int DNSServiceRegistrationUpdateRecord_rpc
96(
97    mach_port_t server,
98    mach_port_t client,
99    natural_t reference,
100    record_data_t data,
101    mach_msg_type_number_t record_dataCnt,
102    uint32_t ttl
103);
104
105extern
106kern_return_t DNSServiceRegistrationRemoveRecord_rpc
107(
108    mach_port_t server,
109    mach_port_t client,
110    natural_t reference
111);
112
113struct a_requests {
114    struct a_requests       *next;
115    mach_port_t client_port;
116    union {
117        DNSServiceBrowserReply browserCallback;
118        DNSServiceDomainEnumerationReply enumCallback;
119        DNSServiceRegistrationReply regCallback;
120        DNSServiceResolverReply resolveCallback;
121    } callout;
122    void                    *context;
123};
124
125static struct a_requests    *a_requests = NULL;
126static pthread_mutex_t a_requests_lock = PTHREAD_MUTEX_INITIALIZER;
127
128typedef struct _dns_service_discovery_t {
129    mach_port_t port;
130} dns_service_discovery_t;
131
132static mach_port_t DNSServiceDiscoveryLookupServer(void)
133{
134    static mach_port_t sndPort  = MACH_PORT_NULL;
135    kern_return_t result;
136
137    if (sndPort != MACH_PORT_NULL) {
138        return sndPort;
139    }
140
141    result = bootstrap_look_up(bootstrap_port, DNS_SERVICE_DISCOVERY_SERVER, &sndPort);
142    if (result != KERN_SUCCESS) {
143        printf("%s(): {%s:%d} bootstrap_look_up() failed: $%x\n", __FUNCTION__, __FILE__, __LINE__, (int) result);
144        sndPort = MACH_PORT_NULL;
145    }
146
147
148    return sndPort;
149}
150
151static void _increaseQueueLengthOnPort(mach_port_t port)
152{
153    mach_port_limits_t qlimits;
154    kern_return_t result;
155
156    qlimits.mpl_qlimit = 16;
157    result = mach_port_set_attributes(mach_task_self(), port, MACH_PORT_LIMITS_INFO, (mach_port_info_t)&qlimits, MACH_PORT_LIMITS_INFO_COUNT);
158
159    if (result != KERN_SUCCESS) {
160        printf("%s(): {%s:%d} mach_port_set_attributes() failed: $%x %s\n", __FUNCTION__, __FILE__, __LINE__, (int) result, mach_error_string(result));
161    }
162}
163
164dns_service_discovery_ref DNSServiceBrowserCreate (const char *regtype, const char *domain, DNSServiceBrowserReply callBack,void *context)
165{
166    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
167    mach_port_t clientPort;
168    kern_return_t result;
169    dns_service_discovery_ref return_t;
170    struct a_requests   *request;
171
172    if (!serverPort) {
173        return NULL;
174    }
175
176    result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
177    if (result != KERN_SUCCESS) {
178        printf("Mach port receive creation failed, %s\n", mach_error_string(result));
179        return NULL;
180    }
181    result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
182    if (result != KERN_SUCCESS) {
183        printf("Mach port send creation failed, %s\n", mach_error_string(result));
184        mach_port_destroy(mach_task_self(), clientPort);
185        return NULL;
186    }
187    _increaseQueueLengthOnPort(clientPort);
188
189    return_t = malloc(sizeof(dns_service_discovery_t));
190    return_t->port = clientPort;
191
192    request = malloc(sizeof(struct a_requests));
193    request->client_port = clientPort;
194    request->context = context;
195    request->callout.browserCallback = callBack;
196
197    result = DNSServiceBrowserCreate_rpc(serverPort, clientPort, (char *)regtype, (char *)domain);
198
199    if (result != KERN_SUCCESS) {
200        printf("There was an error creating a browser, %s\n", mach_error_string(result));
201        free(request);
202        return NULL;
203    }
204
205    pthread_mutex_lock(&a_requests_lock);
206    request->next = a_requests;
207    a_requests = request;
208    pthread_mutex_unlock(&a_requests_lock);
209
210    return return_t;
211}
212
213/* Service Enumeration */
214
215dns_service_discovery_ref DNSServiceDomainEnumerationCreate (int registrationDomains, DNSServiceDomainEnumerationReply callBack, void *context)
216{
217    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
218    mach_port_t clientPort;
219    kern_return_t result;
220    dns_service_discovery_ref return_t;
221    struct a_requests   *request;
222
223    if (!serverPort) {
224        return NULL;
225    }
226
227    result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
228    if (result != KERN_SUCCESS) {
229        printf("Mach port receive creation failed, %s\n", mach_error_string(result));
230        return NULL;
231    }
232    result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
233    if (result != KERN_SUCCESS) {
234        printf("Mach port send creation failed, %s\n", mach_error_string(result));
235        mach_port_destroy(mach_task_self(), clientPort);
236        return NULL;
237    }
238    _increaseQueueLengthOnPort(clientPort);
239
240    return_t = malloc(sizeof(dns_service_discovery_t));
241    return_t->port = clientPort;
242
243    request = malloc(sizeof(struct a_requests));
244    request->client_port = clientPort;
245    request->context = context;
246    request->callout.enumCallback = callBack;
247
248    result = DNSServiceDomainEnumerationCreate_rpc(serverPort, clientPort, registrationDomains);
249
250    if (result != KERN_SUCCESS) {
251        printf("There was an error creating an enumerator, %s\n", mach_error_string(result));
252        free(request);
253        return NULL;
254    }
255
256    pthread_mutex_lock(&a_requests_lock);
257    request->next = a_requests;
258    a_requests = request;
259    pthread_mutex_unlock(&a_requests_lock);
260
261    return return_t;
262}
263
264
265/* Service Registration */
266
267dns_service_discovery_ref DNSServiceRegistrationCreate
268    (const char *name, const char *regtype, const char *domain, uint16_t port, const char *txtRecord, DNSServiceRegistrationReply callBack, void *context)
269{
270    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
271    mach_port_t clientPort;
272    kern_return_t result;
273    dns_service_discovery_ref return_t;
274    struct a_requests   *request;
275    IPPort IpPort;
276    char *portptr = (char *)&port;
277
278    if (!serverPort) {
279        return NULL;
280    }
281
282    if (!txtRecord) {
283        txtRecord = "";
284    }
285
286    result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
287    if (result != KERN_SUCCESS) {
288        printf("Mach port receive creation failed, %s\n", mach_error_string(result));
289        return NULL;
290    }
291    result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
292    if (result != KERN_SUCCESS) {
293        printf("Mach port send creation failed, %s\n", mach_error_string(result));
294        mach_port_destroy(mach_task_self(), clientPort);
295        return NULL;
296    }
297    _increaseQueueLengthOnPort(clientPort);
298
299    return_t = malloc(sizeof(dns_service_discovery_t));
300    return_t->port = clientPort;
301
302    request = malloc(sizeof(struct a_requests));
303    request->client_port = clientPort;
304    request->context = context;
305    request->callout.regCallback = callBack;
306
307    // older versions of this code passed the port via mach IPC as an int.
308    // we continue to pass it as 4 bytes to maintain binary compatibility,
309    // but now ensure that the network byte order is preserved by using a struct
310    IpPort.bytes[0] = 0;
311    IpPort.bytes[1] = 0;
312    IpPort.bytes[2] = portptr[0];
313    IpPort.bytes[3] = portptr[1];
314
315    result = DNSServiceRegistrationCreate_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain, IpPort, (char *)txtRecord);
316
317    if (result != KERN_SUCCESS) {
318        printf("There was an error creating a resolve, %s\n", mach_error_string(result));
319        free(request);
320        return NULL;
321    }
322
323    pthread_mutex_lock(&a_requests_lock);
324    request->next = a_requests;
325    a_requests = request;
326    pthread_mutex_unlock(&a_requests_lock);
327
328    return return_t;
329}
330
331/* Resolver requests */
332
333dns_service_discovery_ref DNSServiceResolverResolve(const char *name, const char *regtype, const char *domain, DNSServiceResolverReply callBack, void *context)
334{
335    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
336    mach_port_t clientPort;
337    kern_return_t result;
338    dns_service_discovery_ref return_t;
339    struct a_requests   *request;
340
341    if (!serverPort) {
342        return NULL;
343    }
344
345    result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
346    if (result != KERN_SUCCESS) {
347        printf("Mach port receive creation failed, %s\n", mach_error_string(result));
348        return NULL;
349    }
350    result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
351    if (result != KERN_SUCCESS) {
352        printf("Mach port send creation failed, %s\n", mach_error_string(result));
353        mach_port_destroy(mach_task_self(), clientPort);
354        return NULL;
355    }
356    _increaseQueueLengthOnPort(clientPort);
357
358    return_t = malloc(sizeof(dns_service_discovery_t));
359    return_t->port = clientPort;
360
361    request = malloc(sizeof(struct a_requests));
362    request->client_port = clientPort;
363    request->context = context;
364    request->callout.resolveCallback = callBack;
365
366    DNSServiceResolverResolve_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain);
367
368    pthread_mutex_lock(&a_requests_lock);
369    request->next = a_requests;
370    a_requests = request;
371    pthread_mutex_unlock(&a_requests_lock);
372
373    return return_t;
374}
375
376DNSRecordReference DNSServiceRegistrationAddRecord(dns_service_discovery_ref ref, uint16_t rrtype, uint16_t rdlen, const char *rdata, uint32_t ttl)
377{
378    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
379    mach_port_t clientPort;
380    natural_t reference = 0;
381    kern_return_t result = KERN_SUCCESS;
382
383    if (!serverPort) {
384        return kDNSServiceDiscoveryUnknownErr;
385    }
386
387    clientPort = DNSServiceDiscoveryMachPort(ref);
388
389    if (!clientPort) {
390        return kDNSServiceDiscoveryUnknownErr;
391    }
392
393    result = DNSServiceRegistrationAddRecord_rpc(serverPort, clientPort, rrtype, (record_data_t)rdata, rdlen, ttl, &reference);
394
395    if (result != KERN_SUCCESS) {
396        printf("The result of the registration was not successful.  Error %d, result %s\n", result, mach_error_string(result));
397    }
398
399    return reference;
400}
401
402DNSServiceRegistrationReplyErrorType DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref, DNSRecordReference reference, uint16_t rdlen, const char *rdata, uint32_t ttl)
403{
404    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
405    mach_port_t clientPort;
406    kern_return_t result = KERN_SUCCESS;
407
408    if (!serverPort) {
409        return kDNSServiceDiscoveryUnknownErr;
410    }
411
412    clientPort = DNSServiceDiscoveryMachPort(ref);
413
414    if (!clientPort) {
415        return kDNSServiceDiscoveryUnknownErr;
416    }
417
418    result = DNSServiceRegistrationUpdateRecord_rpc(serverPort, clientPort, (natural_t)reference, (record_data_t)rdata, rdlen, ttl);
419    if (result != KERN_SUCCESS) {
420        printf("The result of the registration was not successful.  Error %d, result %s\n", result, mach_error_string(result));
421        return result;
422    }
423
424    return kDNSServiceDiscoveryNoError;
425}
426
427
428DNSServiceRegistrationReplyErrorType DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref, DNSRecordReference reference)
429{
430    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
431    mach_port_t clientPort;
432    kern_return_t result = KERN_SUCCESS;
433
434    if (!serverPort) {
435        return kDNSServiceDiscoveryUnknownErr;
436    }
437
438    clientPort = DNSServiceDiscoveryMachPort(ref);
439
440    if (!clientPort) {
441        return kDNSServiceDiscoveryUnknownErr;
442    }
443
444    result = DNSServiceRegistrationRemoveRecord_rpc(serverPort, clientPort, (natural_t)reference);
445
446    if (result != KERN_SUCCESS) {
447        printf("The result of the registration was not successful.  Error %d, result %s\n", result, mach_error_string(result));
448        return result;
449    }
450
451    return kDNSServiceDiscoveryNoError;
452}
453
454void DNSServiceDiscovery_handleReply(void *replyMsg)
455{
456    mach_msg_header_t *     msgSendBufPtr;
457    mach_msg_header_t *     receivedMessage;
458    unsigned msgSendBufLength;
459
460    msgSendBufLength = internal_DNSServiceDiscoveryReply_subsystem.maxsize;
461    msgSendBufPtr = (mach_msg_header_t *) malloc(msgSendBufLength);
462
463
464    receivedMessage = ( mach_msg_header_t * ) replyMsg;
465
466    // Call DNSServiceDiscoveryReply_server to change mig-generated message into a
467    // genuine mach message. It will then cause the callback to get called.
468    DNSServiceDiscoveryReply_server ( receivedMessage, msgSendBufPtr );
469    ( void ) mach_msg_send ( msgSendBufPtr );
470    free(msgSendBufPtr);
471}
472
473mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery)
474{
475    return dnsServiceDiscovery->port;
476}
477
478void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery)
479{
480    struct a_requests   *request0, *request;
481    mach_port_t reply = dnsServiceDiscovery->port;
482
483    if (dnsServiceDiscovery->port) {
484        pthread_mutex_lock(&a_requests_lock);
485        request0 = NULL;
486        request  = a_requests;
487        while (request) {
488            if (request->client_port == reply) {
489                /* request info found, remove from list */
490                if (request0) {
491                    request0->next = request->next;
492                } else {
493                    a_requests = request->next;
494                }
495                break;
496            } else {
497                /* not info for this request, skip to next */
498                request0 = request;
499                request  = request->next;
500            }
501
502        }
503        pthread_mutex_unlock(&a_requests_lock);
504
505        free(request);
506
507        mach_port_destroy(mach_task_self(), dnsServiceDiscovery->port);
508
509        free(dnsServiceDiscovery);
510    }
511    return;
512}
513
514// reply functions, calls the users setup callbacks with function pointers
515
516kern_return_t internal_DNSServiceDomainEnumerationReply_rpc
517(
518    mach_port_t reply,
519    int resultType,
520    DNSCString replyDomain,
521    int flags
522)
523{
524    struct a_requests   *request;
525    void *requestContext = NULL;
526    DNSServiceDomainEnumerationReply callback = NULL;
527
528    pthread_mutex_lock(&a_requests_lock);
529    request  = a_requests;
530    while (request) {
531        if (request->client_port == reply) {
532            break;
533        }
534        request = request->next;
535    }
536
537    if (request != NULL) {
538        callback = (*request->callout.enumCallback);
539        requestContext = request->context;
540    }
541    pthread_mutex_unlock(&a_requests_lock);
542
543    if (request != NULL) {
544        (callback)(resultType, replyDomain, flags, requestContext);
545    }
546
547    return KERN_SUCCESS;
548
549}
550
551kern_return_t internal_DNSServiceBrowserReply_rpc
552(
553    mach_port_t reply,
554    int resultType,
555    DNSCString replyName,
556    DNSCString replyType,
557    DNSCString replyDomain,
558    int flags
559)
560{
561    struct a_requests   *request;
562    void *requestContext = NULL;
563    DNSServiceBrowserReply callback = NULL;
564
565    pthread_mutex_lock(&a_requests_lock);
566    request  = a_requests;
567    while (request) {
568        if (request->client_port == reply) {
569            break;
570        }
571        request = request->next;
572    }
573    if (request != NULL) {
574        callback = (*request->callout.browserCallback);
575        requestContext = request->context;
576    }
577
578    pthread_mutex_unlock(&a_requests_lock);
579
580    if (request != NULL) {
581        (callback)(resultType, replyName, replyType, replyDomain, flags, requestContext);
582    }
583
584    return KERN_SUCCESS;
585}
586
587
588kern_return_t internal_DNSServiceRegistrationReply_rpc
589(
590    mach_port_t reply,
591    int resultType
592)
593{
594    struct a_requests   *request;
595    void *requestContext = NULL;
596    DNSServiceRegistrationReply callback = NULL;
597
598    pthread_mutex_lock(&a_requests_lock);
599    request  = a_requests;
600    while (request) {
601        if (request->client_port == reply) {
602            break;
603        }
604        request = request->next;
605    }
606    if (request != NULL) {
607        callback = (*request->callout.regCallback);
608        requestContext = request->context;
609    }
610
611    pthread_mutex_unlock(&a_requests_lock);
612    if (request != NULL) {
613        (callback)(resultType, requestContext);
614    }
615    return KERN_SUCCESS;
616}
617
618
619kern_return_t internal_DNSServiceResolverReply_rpc
620(
621    mach_port_t reply,
622    sockaddr_t interface,
623    sockaddr_t address,
624    DNSCString txtRecord,
625    int flags
626)
627{
628    struct sockaddr  *interface_storage = NULL;
629    struct sockaddr  *address_storage = NULL;
630    struct a_requests   *request;
631    void *requestContext = NULL;
632    DNSServiceResolverReply callback = NULL;
633
634    if (interface) {
635        int len = ((struct sockaddr *)interface)->sa_len;
636        interface_storage = (struct sockaddr *)malloc(len);
637        memcpy(interface_storage, interface, len);
638    }
639
640    if (address) {
641        int len = ((struct sockaddr *)address)->sa_len;
642        address_storage = (struct sockaddr *)malloc(len);
643        memcpy(address_storage, address, len);
644    }
645
646    pthread_mutex_lock(&a_requests_lock);
647    request  = a_requests;
648    while (request) {
649        if (request->client_port == reply) {
650            break;
651        }
652        request = request->next;
653    }
654
655    if (request != NULL) {
656        callback = (*request->callout.resolveCallback);
657        requestContext = request->context;
658    }
659    pthread_mutex_unlock(&a_requests_lock);
660
661    if (request != NULL) {
662        (callback)(interface_storage, address_storage, txtRecord, flags, requestContext);
663    }
664
665    if (interface) {
666        free(interface_storage);
667    }
668    if (address) {
669        free(address_storage);
670    }
671
672    return KERN_SUCCESS;
673}
Note: See TracBrowser for help on using the repository browser.