2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 #include "dnssd_ipc.h"
32 #define CTL_PATH_PREFIX "/tmp/dnssd_clippath."
33 // error socket (if needed) is named "dnssd_clipath.[pid].xxx:n" where xxx are the
34 // last 3 digits of the time (in seconds) and n is the 6-digit microsecond time
36 // general utility functions
37 static DNSServiceRef
connect_to_server(void);
38 DNSServiceErrorType
deliver_request(void *msg
, DNSServiceRef sdr
, int reuse_sd
);
39 static ipc_msg_hdr
*create_hdr(int op
, int *len
, char **data_start
, int reuse_socket
);
40 static int my_read(int sd
, char *buf
, int len
);
41 static int my_write(int sd
, char *buf
, int len
);
42 static int domain_ends_in_dot(const char *dom
);
43 // server response handlers
44 static void handle_query_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *msg
);
45 static void handle_browse_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
46 static void handle_regservice_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
47 static void handle_regrecord_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
48 static void handle_enumeration_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
49 static void handle_resolve_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
51 typedef struct _DNSServiceRef_t
53 int sockfd
; // connected socket between client and daemon
54 int op
; // request/reply_op_t
55 process_reply_callback process_reply
;
58 uint32_t max_index
; //largest assigned record index - 0 if no additl. recs registered
61 typedef struct _DNSRecordRef_t
64 DNSServiceRegisterRecordReply app_callback
;
66 int record_index
; // index is unique to the ServiceDiscoveryRef
73 int DNSServiceRefSockFD(DNSServiceRef sdRef
)
75 if (!sdRef
) return -1;
79 // handle reply from server, calling application client callback. If there is no reply
80 // from the daemon on the socket contained in sdRef, the call will block.
81 DNSServiceErrorType
DNSServiceProcessResult(DNSServiceRef sdRef
)
86 if (!sdRef
|| sdRef
->sockfd
< 0 || !sdRef
->process_reply
)
87 return kDNSServiceErr_BadReference
;
89 if (my_read(sdRef
->sockfd
, (void *)&hdr
, sizeof(hdr
)) < 0)
90 return kDNSServiceErr_Unknown
;
91 if (hdr
.version
!= VERSION
)
92 return kDNSServiceErr_Incompatible
;
93 data
= malloc(hdr
.datalen
);
94 if (!data
) return kDNSServiceErr_NoMemory
;
95 if (my_read(sdRef
->sockfd
, data
, hdr
.datalen
) < 0)
96 return kDNSServiceErr_Unknown
;
97 sdRef
->process_reply(sdRef
, &hdr
, data
);
99 return kDNSServiceErr_NoError
;
103 void DNSServiceRefDeallocate(DNSServiceRef sdRef
)
106 if (sdRef
->sockfd
> 0) close(sdRef
->sockfd
);
111 DNSServiceErrorType DNSServiceResolve
113 DNSServiceRef
*sdRef
,
114 const DNSServiceFlags flags
,
115 const uint32_t interfaceIndex
,
119 const DNSServiceResolveReply callBack
,
123 char *msg
= NULL
, *ptr
;
127 DNSServiceErrorType err
;
129 if (!sdRef
) return kDNSServiceErr_BadParam
;
132 // calculate total message length
134 len
+= sizeof(interfaceIndex
);
135 len
+= strlen(name
) + 1;
136 len
+= strlen(regtype
) + 1;
137 len
+= strlen(domain
) + 1;
139 hdr
= create_hdr(resolve_request
, &len
, &ptr
, 1);
140 if (!hdr
) goto error
;
143 put_flags(flags
, &ptr
);
144 put_long(interfaceIndex
, &ptr
);
145 put_string(name
, &ptr
);
146 put_string(regtype
, &ptr
);
147 put_string(domain
, &ptr
);
149 sdr
= connect_to_server();
150 if (!sdr
) goto error
;
151 err
= deliver_request(msg
, sdr
, 1);
154 DNSServiceRefDeallocate(sdr
);
157 sdr
->op
= resolve_request
;
158 sdr
->process_reply
= handle_resolve_response
;
159 sdr
->app_callback
= callBack
;
160 sdr
->app_context
= context
;
167 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
168 return kDNSServiceErr_Unknown
;
172 static void handle_resolve_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
174 DNSServiceFlags flags
;
175 char fullname
[kDNSServiceMaxDomainName
];
176 char target
[kDNSServiceMaxDomainName
];
177 uint16_t port
, txtlen
;
179 DNSServiceErrorType err
;
184 flags
= get_flags(&data
);
185 ifi
= get_long(&data
);
186 err
= get_error_code(&data
);
187 get_string(&data
, fullname
, kDNSServiceMaxDomainName
);
188 get_string(&data
, target
, kDNSServiceMaxDomainName
);
189 port
= get_short(&data
);
190 txtlen
= get_short(&data
);
191 txtrecord
= get_rdata(&data
, txtlen
);
193 ((DNSServiceResolveReply
)sdr
->app_callback
)(sdr
, flags
, ifi
, err
, fullname
, target
, port
, txtlen
, txtrecord
, sdr
->app_context
);
199 DNSServiceErrorType DNSServiceQueryRecord
201 DNSServiceRef
*sdRef
,
202 const DNSServiceFlags flags
,
203 const uint32_t interfaceIndex
,
205 const uint16_t rrtype
,
206 const uint16_t rrclass
,
207 const DNSServiceQueryRecordReply callBack
,
211 char *msg
= NULL
, *ptr
;
215 DNSServiceErrorType err
;
217 if (!sdRef
) return kDNSServiceErr_BadParam
;
220 if (!name
) name
= "\0";
222 // calculate total message length
224 len
+= sizeof(uint32_t); //interfaceIndex
225 len
+= strlen(name
) + 1;
226 len
+= 2 * sizeof(uint16_t); // rrtype, rrclass
228 hdr
= create_hdr(query_request
, &len
, &ptr
, 1);
229 if (!hdr
) goto error
;
232 put_flags(flags
, &ptr
);
233 put_long(interfaceIndex
, &ptr
);
234 put_string(name
, &ptr
);
235 put_short(rrtype
, &ptr
);
236 put_short(rrclass
, &ptr
);
238 sdr
= connect_to_server();
239 if (!sdr
) goto error
;
240 err
= deliver_request(msg
, sdr
, 1);
243 DNSServiceRefDeallocate(sdr
);
247 sdr
->op
= query_request
;
248 sdr
->process_reply
= handle_query_response
;
249 sdr
->app_callback
= callBack
;
250 sdr
->app_context
= context
;
256 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
257 return kDNSServiceErr_Unknown
;
261 static void handle_query_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
263 DNSServiceFlags flags
;
264 uint32_t interfaceIndex
, ttl
;
265 DNSServiceErrorType errorCode
;
267 uint16_t rrtype
, rrclass
, rdlen
;
271 flags
= get_flags(&data
);
272 interfaceIndex
= get_long(&data
);
273 errorCode
= get_error_code(&data
);
274 (get_string(&data
, name
, 256) < 0);
275 rrtype
= get_short(&data
);
276 rrclass
= get_short(&data
);
277 rdlen
= get_short(&data
);
278 rdata
= get_rdata(&data
, rdlen
);
279 ttl
= get_long(&data
);
281 ((DNSServiceQueryRecordReply
)sdr
->app_callback
)(sdr
, flags
, interfaceIndex
, errorCode
, name
, rrtype
, rrclass
,
282 rdlen
, rdata
, ttl
, sdr
->app_context
);
286 DNSServiceErrorType DNSServiceBrowse
288 DNSServiceRef
*sdRef
,
289 const DNSServiceFlags flags
,
290 const uint32_t interfaceIndex
,
293 const DNSServiceBrowseReply callBack
,
297 char *msg
= NULL
, *ptr
;
301 DNSServiceErrorType err
;
303 if (!sdRef
) return kDNSServiceErr_BadParam
;
306 if (!domain
) domain
= "";
309 len
+= sizeof(interfaceIndex
);
310 len
+= strlen(regtype
) + 1;
311 len
+= strlen(domain
) + 1;
313 hdr
= create_hdr(browse_request
, &len
, &ptr
, 1);
314 if (!hdr
) goto error
;
316 put_flags(flags
, &ptr
);
317 put_long(interfaceIndex
, &ptr
);
318 put_string(regtype
, &ptr
);
319 put_string(domain
, &ptr
);
321 sdr
= connect_to_server();
322 if (!sdr
) goto error
;
323 err
= deliver_request(msg
, sdr
, 1);
326 DNSServiceRefDeallocate(sdr
);
329 sdr
->op
= browse_request
;
330 sdr
->process_reply
= handle_browse_response
;
331 sdr
->app_callback
= callBack
;
332 sdr
->app_context
= context
;
338 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
339 return kDNSServiceErr_Unknown
;
345 static void handle_browse_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
347 DNSServiceFlags flags
;
348 uint32_t interfaceIndex
;
349 DNSServiceErrorType errorCode
;
350 char replyName
[256], replyType
[256], replyDomain
[256];
353 flags
= get_flags(&data
);
354 interfaceIndex
= get_long(&data
);
355 errorCode
= get_error_code(&data
);
356 get_string(&data
, replyName
, 256);
357 get_string(&data
, replyType
, 256);
358 get_string(&data
, replyDomain
, 256);
359 ((DNSServiceBrowseReply
)sdr
->app_callback
)(sdr
, flags
, interfaceIndex
, errorCode
, replyName
, replyType
, replyDomain
, sdr
->app_context
);
363 DNSServiceErrorType DNSServiceRegister
365 DNSServiceRef
*sdRef
,
366 const DNSServiceFlags flags
,
367 const uint32_t interfaceIndex
,
373 const uint16_t txtLen
,
374 const void *txtRecord
,
375 const DNSServiceRegisterReply callBack
,
379 char *msg
= NULL
, *ptr
;
383 DNSServiceErrorType err
;
385 if (!sdRef
) return kDNSServiceErr_BadParam
;
388 if (!name
) name
= "";
389 if (!regtype
) return kDNSServiceErr_BadParam
;
390 if (!domain
) domain
= "";
391 if (!host
) host
= "";
392 if (!txtRecord
) (char *)txtRecord
= "";
394 // auto-name must also have auto-rename
395 if (!name
[0] && (flags
& kDNSServiceFlagsNoAutoRename
))
396 return kDNSServiceErr_BadParam
;
398 // no callback must have auto-name
399 if (!callBack
&& name
[0]) return kDNSServiceErr_BadParam
;
401 len
= sizeof(DNSServiceFlags
);
402 len
+= sizeof(uint32_t); // interfaceIndex
403 len
+= strlen(name
) + strlen(regtype
) + strlen(domain
) + strlen(host
) + 4;
404 len
+= 2 * sizeof(uint16_t); // port, txtLen
407 hdr
= create_hdr(reg_service_request
, &len
, &ptr
, 1);
408 if (!hdr
) goto error
;
409 if (!callBack
) hdr
->flags
|= IPC_FLAGS_NOREPLY
;
411 put_flags(flags
, &ptr
);
412 put_long(interfaceIndex
, &ptr
);
413 put_string(name
, &ptr
);
414 put_string(regtype
, &ptr
);
415 put_string(domain
, &ptr
);
416 put_string(host
, &ptr
);
417 put_short(port
, &ptr
);
418 put_short(txtLen
, &ptr
);
419 put_rdata(txtLen
, txtRecord
, &ptr
);
421 sdr
= connect_to_server();
422 if (!sdr
) goto error
;
423 err
= deliver_request(msg
, sdr
, 1);
426 DNSServiceRefDeallocate(sdr
);
430 sdr
->op
= reg_service_request
;
431 sdr
->process_reply
= callBack ? handle_regservice_response
: NULL
;
432 sdr
->app_callback
= callBack
;
433 sdr
->app_context
= context
;
440 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
441 return kDNSServiceErr_Unknown
;
445 static void handle_regservice_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
447 DNSServiceFlags flags
;
448 uint32_t interfaceIndex
;
449 DNSServiceErrorType errorCode
;
450 char name
[256], regtype
[256], domain
[256];
453 flags
= get_flags(&data
);
454 interfaceIndex
= get_long(&data
);
455 errorCode
= get_error_code(&data
);
456 get_string(&data
, name
, 256);
457 get_string(&data
, regtype
, 256);
458 get_string(&data
, domain
, 256);
459 ((DNSServiceRegisterReply
)sdr
->app_callback
)(sdr
, flags
, errorCode
, name
, regtype
, domain
, sdr
->app_context
);
462 DNSServiceErrorType DNSServiceEnumerateDomains
464 DNSServiceRef
*sdRef
,
465 const DNSServiceFlags flags
,
466 const uint32_t interfaceIndex
,
467 const DNSServiceDomainEnumReply callBack
,
471 char *msg
= NULL
, *ptr
;
475 DNSServiceErrorType err
;
478 if (!sdRef
) return kDNSServiceErr_BadParam
;
481 len
= sizeof(DNSServiceFlags
);
482 len
+= sizeof(uint32_t);
484 hdr
= create_hdr(enumeration_request
, &len
, &ptr
, 1);
485 if (!hdr
) goto error
;
488 put_flags(flags
, &ptr
);
489 put_long(interfaceIndex
, &ptr
);
491 sdr
= connect_to_server();
492 if (!sdr
) goto error
;
493 err
= deliver_request(msg
, sdr
, 1);
496 DNSServiceRefDeallocate(sdr
);
500 sdr
->op
= enumeration_request
;
501 sdr
->process_reply
= handle_enumeration_response
;
502 sdr
->app_callback
= callBack
;
503 sdr
->app_context
= context
;
509 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
510 return kDNSServiceErr_Unknown
;
514 static void handle_enumeration_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
516 DNSServiceFlags flags
;
517 uint32_t interfaceIndex
;
518 DNSServiceErrorType err
;
522 flags
= get_flags(&data
);
523 interfaceIndex
= get_long(&data
);
524 err
= get_error_code(&data
);
525 get_string(&data
, domain
, 256);
526 ((DNSServiceDomainEnumReply
)sdr
->app_callback
)(sdr
, flags
, interfaceIndex
, err
, domain
, sdr
->app_context
);
530 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
532 if (!sdRef
) return kDNSServiceErr_BadParam
;
533 *sdRef
= connect_to_server();
535 return kDNSServiceErr_Unknown
;
536 (*sdRef
)->op
= connection
;
537 (*sdRef
)->process_reply
= handle_regrecord_response
;
543 static void handle_regrecord_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
545 DNSServiceFlags flags
;
546 uint32_t interfaceIndex
;
547 DNSServiceErrorType errorCode
;
548 DNSRecordRef rref
= hdr
->client_context
.context
;
550 if (sdr
->op
!= connection
)
552 rref
->app_callback(rref
->sdr
, rref
, 0, kDNSServiceErr_Unknown
, rref
->app_context
);
555 flags
= get_flags(&data
);
556 interfaceIndex
= get_long(&data
);
557 errorCode
= get_error_code(&data
);
559 rref
->app_callback(rref
->sdr
, rref
, flags
, errorCode
, rref
->app_context
);
562 DNSServiceErrorType DNSServiceRegisterRecord
564 const DNSServiceRef sdRef
,
565 DNSRecordRef
*RecordRef
,
566 const DNSServiceFlags flags
,
567 const uint32_t interfaceIndex
,
568 const char *fullname
,
569 const uint16_t rrtype
,
570 const uint16_t rrclass
,
571 const uint16_t rdlen
,
574 const DNSServiceRegisterRecordReply callBack
,
578 char *msg
= NULL
, *ptr
;
580 ipc_msg_hdr
*hdr
= NULL
;
581 DNSServiceRef tmp
= NULL
;
582 DNSRecordRef rref
= NULL
;
584 if (!sdRef
|| sdRef
->op
!= connection
|| sdRef
->sockfd
< 0)
585 return kDNSServiceErr_BadReference
;
588 len
= sizeof(DNSServiceFlags
);
589 len
+= 2 * sizeof(uint32_t); // interfaceIndex, ttl
590 len
+= 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen
591 len
+= strlen(fullname
) + 1;
594 hdr
= create_hdr(reg_record_request
, &len
, &ptr
, 0);
595 if (!hdr
) goto error
;
597 put_flags(flags
, &ptr
);
598 put_long(interfaceIndex
, &ptr
);
599 put_string(fullname
, &ptr
);
600 put_short(rrtype
, &ptr
);
601 put_short(rrclass
, &ptr
);
602 put_short(rdlen
, &ptr
);
603 put_rdata(rdlen
, rdata
, &ptr
);
606 rref
= malloc(sizeof(_DNSRecordRef_t
));
607 if (!rref
) goto error
;
608 rref
->app_context
= context
;
609 rref
->app_callback
= callBack
;
610 rref
->record_index
= sdRef
->max_index
++;
613 hdr
->client_context
.context
= rref
;
614 hdr
->reg_index
= rref
->record_index
;
616 return deliver_request(msg
, sdRef
, 0);
619 if (rref
) free(rref
);
622 return kDNSServiceErr_Unknown
;
625 //sdRef returned by DNSServiceRegister()
626 DNSServiceErrorType DNSServiceAddRecord
628 const DNSServiceRef sdRef
,
629 DNSRecordRef
*RecordRef
,
630 const DNSServiceFlags flags
,
631 const uint16_t rrtype
,
632 const uint16_t rdlen
,
642 if (!sdRef
|| (sdRef
->op
!= reg_service_request
) || !RecordRef
)
643 return kDNSServiceErr_BadReference
;
646 len
+= 2 * sizeof(uint16_t); //rrtype, rdlen
648 len
+= sizeof(uint32_t);
649 len
+= sizeof(DNSServiceFlags
);
651 hdr
= create_hdr(add_record_request
, &len
, &ptr
, 0);
652 if (!hdr
) return kDNSServiceErr_Unknown
;
653 put_flags(flags
, &ptr
);
654 put_short(rrtype
, &ptr
);
655 put_short(rdlen
, &ptr
);
656 put_rdata(rdlen
, rdata
, &ptr
);
659 rref
= malloc(sizeof(_DNSRecordRef_t
));
660 if (!rref
) goto error
;
661 rref
->app_context
= NULL
;
662 rref
->app_callback
= NULL
;
663 rref
->record_index
= sdRef
->max_index
++;
666 hdr
->client_context
.context
= rref
;
667 hdr
->reg_index
= rref
->record_index
;
668 return deliver_request((char *)hdr
, sdRef
, 0);
672 if (rref
) free(rref
);
673 if (*RecordRef
) *RecordRef
= NULL
;
674 return kDNSServiceErr_Unknown
;
678 //DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord
679 DNSServiceErrorType DNSServiceUpdateRecord
681 const DNSServiceRef sdRef
,
682 DNSRecordRef RecordRef
,
683 const DNSServiceFlags flags
,
684 const uint16_t rdlen
,
693 if (!sdRef
|| !RecordRef
|| !sdRef
->max_index
)
694 return kDNSServiceErr_BadReference
;
696 len
+= sizeof(uint16_t);
698 len
+= sizeof(uint32_t);
699 len
+= sizeof(DNSServiceFlags
);
701 hdr
= create_hdr(update_record_request
, &len
, &ptr
, 0);
702 if (!hdr
) return kDNSServiceErr_Unknown
;
703 hdr
->reg_index
= RecordRef ? RecordRef
->record_index
: TXT_RECORD_INDEX
;
704 put_flags(flags
, &ptr
);
705 put_short(rdlen
, &ptr
);
706 put_rdata(rdlen
, rdata
, &ptr
);
708 return deliver_request((char *)hdr
, sdRef
, 0);
713 DNSServiceErrorType DNSServiceRemoveRecord
715 const DNSServiceRef sdRef
,
716 const DNSRecordRef RecordRef
,
717 const DNSServiceFlags flags
723 DNSServiceErrorType err
;
725 if (!sdRef
|| !RecordRef
|| !sdRef
->max_index
)
726 return kDNSServiceErr_BadReference
;
728 len
+= sizeof(flags
);
729 hdr
= create_hdr(remove_record_request
, &len
, &ptr
, 0);
730 if (!hdr
) return kDNSServiceErr_Unknown
;
731 hdr
->reg_index
= RecordRef
->record_index
;
732 put_flags(flags
, &ptr
);
733 err
= deliver_request((char *)hdr
, sdRef
, 0);
734 if (!err
) free(RecordRef
);
739 void DNSServiceReconfirmRecord
741 const DNSServiceFlags flags
,
742 const uint32_t interfaceIndex
,
743 const char *fullname
,
744 const uint16_t rrtype
,
745 const uint16_t rrclass
,
746 const uint16_t rdlen
,
755 len
= sizeof(DNSServiceFlags
);
756 len
+= sizeof(uint32_t);
757 len
+= strlen(fullname
) + 1;
758 len
+= 3 * sizeof(uint16_t);
760 tmp
= connect_to_server();
762 hdr
= create_hdr(reconfirm_record_request
, &len
, &ptr
, 1);
765 put_flags(flags
, &ptr
);
766 put_long(interfaceIndex
, &ptr
);
767 put_string(fullname
, &ptr
);
768 put_short(rrtype
, &ptr
);
769 put_short(rrclass
, &ptr
);
770 put_short(rdlen
, &ptr
);
771 put_rdata(rdlen
, rdata
, &ptr
);
772 my_write(tmp
->sockfd
, (char *)hdr
, len
);
773 DNSServiceRefDeallocate(tmp
);
777 int DNSServiceConstructFullName
780 const char *service
, /* may be NULL */
788 const char *s
= service
;
789 const char *r
= regtype
;
790 const char *d
= domain
;
797 if (c
== '.' || (c
== '\\')) *fn
++ = '\\'; // escape dot and backslash literals
798 else if (c
<= ' ') // escape non-printable characters
801 *fn
++ = (char) ('0' + (c
/ 100));
802 *fn
++ = (char) ('0' + (c
/ 10) % 10);
803 c
= (u_char
)('0' + (c
% 10));
810 if (!regtype
) return -1;
811 len
= strlen(regtype
);
812 if (domain_ends_in_dot(regtype
)) len
--;
813 if (len
< 4) return -1; // regtype must end in _udp or _tcp
814 if (strncmp((regtype
+ len
- 4), "_tcp", 4) && strncmp((regtype
+ len
- 4), "_udp", 4)) return -1;
817 if (!domain_ends_in_dot(regtype
)) *fn
++ = '.';
819 if (!domain
) return -1;
820 len
= strlen(domain
);
824 if (!domain_ends_in_dot(domain
)) *fn
++ = '.';
829 static int domain_ends_in_dot(const char *dom
)
831 while(*dom
&& *(dom
+ 1))
833 if (*dom
== '\\') // advance past escaped byte sequence
835 if (*(dom
+ 1) >= '0' && *(dom
+ 1) <= '9') dom
+= 4;
838 else dom
++; // else read one character
840 return (*dom
== '.');
845 // return a connected service ref (deallocate with DNSServiceRefDeallocate)
846 static DNSServiceRef
connect_to_server(void)
848 struct sockaddr_un saddr
;
851 sdr
= malloc(sizeof(_DNSServiceRef_t
));
852 if (!sdr
) return NULL
;
854 if ((sdr
->sockfd
= socket(AF_LOCAL
, SOCK_STREAM
, 0)) < 0)
860 saddr
.sun_family
= AF_LOCAL
;
861 strcpy(saddr
.sun_path
, MDNS_UDS_SERVERPATH
);
862 if (connect(sdr
->sockfd
, (struct sockaddr
*)&saddr
, sizeof(saddr
)) < 0)
873 int my_write(int sd
, char *buf
, int len
)
875 if (send(sd
, buf
, len
, MSG_WAITALL
) != len
) return -1;
880 // read len bytes. return 0 on success, -1 on error
881 int my_read(int sd
, char *buf
, int len
)
883 if (recv(sd
, buf
, len
, MSG_WAITALL
) != len
) return -1;
888 DNSServiceErrorType
deliver_request(void *msg
, DNSServiceRef sdr
, int reuse_sd
)
890 ipc_msg_hdr
*hdr
= msg
;
892 struct sockaddr_un caddr
, daddr
; // (client and daemon address structs)
894 int listenfd
= -1, errsd
= -1, len
;
895 DNSServiceErrorType err
= kDNSServiceErr_Unknown
;
897 if (!hdr
|| sdr
->sockfd
< 0) return kDNSServiceErr_Unknown
;
901 // setup temporary error socket
902 if ((listenfd
= socket(AF_LOCAL
, SOCK_STREAM
, 0)) < 0)
905 bzero(&caddr
, sizeof(caddr
));
906 caddr
.sun_family
= AF_LOCAL
;
907 caddr
.sun_len
= sizeof(struct sockaddr_un
);
908 path
= (char *)msg
+ sizeof(ipc_msg_hdr
);
909 strcpy(caddr
.sun_path
, path
);
911 if (bind(listenfd
, (struct sockaddr
*)&caddr
, sizeof(caddr
)) < 0)
920 if (my_write(sdr
->sockfd
, msg
, hdr
->datalen
+ sizeof(ipc_msg_hdr
)) < 0)
925 if (reuse_sd
) errsd
= sdr
->sockfd
;
929 errsd
= accept(listenfd
, (struct sockaddr
*)&daddr
, &len
);
930 if (errsd
< 0) goto cleanup
;
933 len
= recv(errsd
, &err
, sizeof(err
), MSG_WAITALL
);
934 if (len
!= sizeof(err
))
936 err
= kDNSServiceErr_Unknown
;
939 if (!reuse_sd
&& listenfd
> 0) close(listenfd
);
940 if (!reuse_sd
&& errsd
> 0) close(errsd
);
941 if (!reuse_sd
&& path
) unlink(path
);
950 * allocate and initialize an ipc message header. value of len should initially be the
951 * length of the data, and is set to the value of the data plus the header. data_start
952 * is set to point to the beginning of the data section. reuse_socket should be non-zero
953 * for calls that can receive an immediate error return value on their primary socket.
954 * if zero, the path to a control socket is appended at the beginning of the message buffer.
955 * data_start is set past this string.
958 static ipc_msg_hdr
*create_hdr(int op
, int *len
, char **data_start
, int reuse_socket
)
968 if (gettimeofday(&time
, NULL
) < 0) return NULL
;
969 sprintf(ctrl_path
, "%s%d-%.3x-%.6u", CTL_PATH_PREFIX
, (int)getpid(),
970 time
.tv_sec
& 0xFFF, time
.tv_usec
);
972 *len
+= strlen(ctrl_path
) + 1;
977 *len
+= sizeof(ipc_msg_hdr
);
979 // write message to buffer
981 if (!msg
) return NULL
;
985 hdr
->datalen
= datalen
;
986 hdr
->version
= VERSION
;
987 hdr
->op
.request_op
= op
;
988 if (reuse_socket
) hdr
->flags
|= IPC_FLAGS_REUSE_SOCKET
;
989 *data_start
= msg
+ sizeof(ipc_msg_hdr
);
990 if (!reuse_socket
) put_string(ctrl_path
, data_start
);