2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
25 $Log: dnssd_clientstub.c,v $
26 Revision 1.9 2003/08/15 21:30:39 cheshire
27 Bring up to date with LibInfo version
29 Revision 1.8 2003/08/13 23:54:52 ksekar
30 Bringing dnssd_clientstub.c up to date with Libinfo, per radar 3376640
32 Revision 1.7 2003/08/12 19:56:25 cheshire
37 #include "dnssd_ipc.h"
39 #define CTL_PATH_PREFIX "/tmp/dnssd_clippath."
40 // error socket (if needed) is named "dnssd_clipath.[pid].xxx:n" where xxx are the
41 // last 3 digits of the time (in seconds) and n is the 6-digit microsecond time
43 // general utility functions
44 static DNSServiceRef
connect_to_server(void);
45 DNSServiceErrorType
deliver_request(void *msg
, DNSServiceRef sdr
, int reuse_sd
);
46 static ipc_msg_hdr
*create_hdr(int op
, int *len
, char **data_start
, int reuse_socket
);
47 static int my_read(int sd
, char *buf
, int len
);
48 static int my_write(int sd
, char *buf
, int len
);
49 static int domain_ends_in_dot(const char *dom
);
50 // server response handlers
51 static void handle_query_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *msg
);
52 static void handle_browse_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
53 static void handle_regservice_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
54 static void handle_regrecord_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
55 static void handle_enumeration_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
56 static void handle_resolve_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
58 typedef struct _DNSServiceRef_t
60 int sockfd
; // connected socket between client and daemon
61 int op
; // request/reply_op_t
62 process_reply_callback process_reply
;
65 uint32_t max_index
; //largest assigned record index - 0 if no additl. recs registered
68 typedef struct _DNSRecordRef_t
71 DNSServiceRegisterRecordReply app_callback
;
73 int record_index
; // index is unique to the ServiceDiscoveryRef
80 int DNSServiceRefSockFD(DNSServiceRef sdRef
)
82 if (!sdRef
) return -1;
86 // handle reply from server, calling application client callback. If there is no reply
87 // from the daemon on the socket contained in sdRef, the call will block.
88 DNSServiceErrorType
DNSServiceProcessResult(DNSServiceRef sdRef
)
93 if (!sdRef
|| sdRef
->sockfd
< 0 || !sdRef
->process_reply
)
94 return kDNSServiceErr_BadReference
;
96 if (my_read(sdRef
->sockfd
, (void *)&hdr
, sizeof(hdr
)) < 0)
97 return kDNSServiceErr_Unknown
;
98 if (hdr
.version
!= VERSION
)
99 return kDNSServiceErr_Incompatible
;
100 data
= malloc(hdr
.datalen
);
101 if (!data
) return kDNSServiceErr_NoMemory
;
102 if (my_read(sdRef
->sockfd
, data
, hdr
.datalen
) < 0)
103 return kDNSServiceErr_Unknown
;
104 sdRef
->process_reply(sdRef
, &hdr
, data
);
105 return kDNSServiceErr_Unknown
;
109 void DNSServiceRefDeallocate(DNSServiceRef sdRef
)
112 if (sdRef
->sockfd
> 0) close(sdRef
->sockfd
);
117 DNSServiceErrorType DNSServiceResolve
119 DNSServiceRef
*sdRef
,
120 const DNSServiceFlags flags
,
121 const uint32_t interfaceIndex
,
125 const DNSServiceResolveReply callBack
,
129 char *msg
= NULL
, *ptr
;
133 DNSServiceErrorType err
;
135 if (!sdRef
) return kDNSServiceErr_BadParam
;
138 // calculate total message length
140 len
+= sizeof(interfaceIndex
);
141 len
+= strlen(name
) + 1;
142 len
+= strlen(regtype
) + 1;
143 len
+= strlen(domain
) + 1;
145 hdr
= create_hdr(resolve_request
, &len
, &ptr
, 1);
146 if (!hdr
) goto error
;
149 put_flags(flags
, &ptr
);
150 put_long(interfaceIndex
, &ptr
);
151 put_string(name
, &ptr
);
152 put_string(regtype
, &ptr
);
153 put_string(domain
, &ptr
);
155 sdr
= connect_to_server();
156 if (!sdr
) goto error
;
157 err
= deliver_request(msg
, sdr
, 1);
160 DNSServiceRefDeallocate(sdr
);
163 sdr
->op
= resolve_request
;
164 sdr
->process_reply
= handle_resolve_response
;
165 sdr
->app_callback
= callBack
;
166 sdr
->app_context
= context
;
173 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
174 return kDNSServiceErr_Unknown
;
178 static void handle_resolve_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
180 DNSServiceFlags flags
;
181 char fullname
[kDNSServiceMaxDomainName
];
182 char target
[kDNSServiceMaxDomainName
];
183 uint16_t port
, txtlen
;
185 DNSServiceErrorType err
;
190 flags
= get_flags(&data
);
191 ifi
= get_long(&data
);
192 err
= get_error_code(&data
);
193 get_string(&data
, fullname
, kDNSServiceMaxDomainName
);
194 get_string(&data
, target
, kDNSServiceMaxDomainName
);
195 port
= get_short(&data
);
196 txtlen
= get_short(&data
);
197 txtrecord
= get_rdata(&data
, txtlen
);
199 ((DNSServiceResolveReply
)sdr
->app_callback
)(sdr
, flags
, ifi
, err
, fullname
, target
, port
, txtlen
, txtrecord
, sdr
->app_context
);
205 DNSServiceErrorType DNSServiceQueryRecord
207 DNSServiceRef
*sdRef
,
208 const DNSServiceFlags flags
,
209 const uint32_t interfaceIndex
,
211 const uint16_t rrtype
,
212 const uint16_t rrclass
,
213 const DNSServiceQueryRecordReply callBack
,
217 char *msg
= NULL
, *ptr
;
221 DNSServiceErrorType err
;
223 if (!sdRef
) return kDNSServiceErr_BadParam
;
226 if (!name
) name
= "\0";
228 // calculate total message length
230 len
+= sizeof(uint32_t); //interfaceIndex
231 len
+= strlen(name
) + 1;
232 len
+= 2 * sizeof(uint16_t); // rrtype, rrclass
234 hdr
= create_hdr(query_request
, &len
, &ptr
, 1);
235 if (!hdr
) goto error
;
238 put_flags(flags
, &ptr
);
239 put_long(interfaceIndex
, &ptr
);
240 put_string(name
, &ptr
);
241 put_short(rrtype
, &ptr
);
242 put_short(rrclass
, &ptr
);
244 sdr
= connect_to_server();
245 if (!sdr
) goto error
;
246 err
= deliver_request(msg
, sdr
, 1);
249 DNSServiceRefDeallocate(sdr
);
253 sdr
->op
= query_request
;
254 sdr
->process_reply
= handle_query_response
;
255 sdr
->app_callback
= callBack
;
256 sdr
->app_context
= context
;
262 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
263 return kDNSServiceErr_Unknown
;
267 static void handle_query_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
269 DNSServiceFlags flags
;
270 uint32_t interfaceIndex
, ttl
;
271 DNSServiceErrorType errorCode
;
273 uint16_t rrtype
, rrclass
, rdlen
;
277 flags
= get_flags(&data
);
278 interfaceIndex
= get_long(&data
);
279 errorCode
= get_error_code(&data
);
280 (get_string(&data
, name
, 256) < 0);
281 rrtype
= get_short(&data
);
282 rrclass
= get_short(&data
);
283 rdlen
= get_short(&data
);
284 rdata
= get_rdata(&data
, rdlen
);
285 ttl
= get_long(&data
);
287 ((DNSServiceQueryRecordReply
)sdr
->app_callback
)(sdr
, flags
, interfaceIndex
, errorCode
, name
, rrtype
, rrclass
,
288 rdlen
, rdata
, ttl
, sdr
->app_context
);
292 DNSServiceErrorType DNSServiceBrowse
294 DNSServiceRef
*sdRef
,
295 const DNSServiceFlags flags
,
296 const uint32_t interfaceIndex
,
299 const DNSServiceBrowseReply callBack
,
303 char *msg
= NULL
, *ptr
;
307 DNSServiceErrorType err
;
309 if (!sdRef
) return kDNSServiceErr_BadParam
;
312 if (!domain
) domain
= "";
315 len
+= sizeof(interfaceIndex
);
316 len
+= strlen(regtype
) + 1;
317 len
+= strlen(domain
) + 1;
319 hdr
= create_hdr(browse_request
, &len
, &ptr
, 1);
320 if (!hdr
) goto error
;
322 put_flags(flags
, &ptr
);
323 put_long(interfaceIndex
, &ptr
);
324 put_string(regtype
, &ptr
);
325 put_string(domain
, &ptr
);
327 sdr
= connect_to_server();
328 if (!sdr
) goto error
;
329 err
= deliver_request(msg
, sdr
, 1);
332 DNSServiceRefDeallocate(sdr
);
335 sdr
->op
= browse_request
;
336 sdr
->process_reply
= handle_browse_response
;
337 sdr
->app_callback
= callBack
;
338 sdr
->app_context
= context
;
344 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
345 return kDNSServiceErr_Unknown
;
351 static void handle_browse_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
353 DNSServiceFlags flags
;
354 uint32_t interfaceIndex
;
355 DNSServiceErrorType errorCode
;
356 char replyName
[256], replyType
[256], replyDomain
[256];
359 flags
= get_flags(&data
);
360 interfaceIndex
= get_long(&data
);
361 errorCode
= get_error_code(&data
);
362 get_string(&data
, replyName
, 256);
363 get_string(&data
, replyType
, 256);
364 get_string(&data
, replyDomain
, 256);
365 ((DNSServiceBrowseReply
)sdr
->app_callback
)(sdr
, flags
, interfaceIndex
, errorCode
, replyName
, replyType
, replyDomain
, sdr
->app_context
);
369 DNSServiceErrorType DNSServiceRegister
371 DNSServiceRef
*sdRef
,
372 const DNSServiceFlags flags
,
373 const uint32_t interfaceIndex
,
379 const uint16_t txtLen
,
380 const void *txtRecord
,
381 const DNSServiceRegisterReply callBack
,
385 char *msg
= NULL
, *ptr
;
389 DNSServiceErrorType err
;
391 if (!sdRef
) return kDNSServiceErr_BadParam
;
394 if (!name
) name
= "";
395 if (!regtype
) return kDNSServiceErr_BadParam
;
396 if (!domain
) domain
= "";
397 if (!host
) host
= "";
398 if (!txtRecord
) (char *)txtRecord
= "";
400 // auto-name must also have auto-rename
401 if (!name
[0] && (flags
& kDNSServiceFlagsNoAutoRename
))
402 return kDNSServiceErr_BadParam
;
404 // no callback must have auto-name
405 if (!callBack
&& name
[0]) return kDNSServiceErr_BadParam
;
407 len
= sizeof(DNSServiceFlags
);
408 len
+= sizeof(uint32_t); // interfaceIndex
409 len
+= strlen(name
) + strlen(regtype
) + strlen(domain
) + strlen(host
) + 4;
410 len
+= 2 * sizeof(uint16_t); // port, txtLen
413 hdr
= create_hdr(reg_service_request
, &len
, &ptr
, 1);
414 if (!hdr
) goto error
;
415 if (!callBack
) hdr
->flags
|= IPC_FLAGS_NOREPLY
;
417 put_flags(flags
, &ptr
);
418 put_long(interfaceIndex
, &ptr
);
419 put_string(name
, &ptr
);
420 put_string(regtype
, &ptr
);
421 put_string(domain
, &ptr
);
422 put_string(host
, &ptr
);
423 put_short(port
, &ptr
);
424 put_short(txtLen
, &ptr
);
425 put_rdata(txtLen
, txtRecord
, &ptr
);
427 sdr
= connect_to_server();
428 if (!sdr
) goto error
;
429 err
= deliver_request(msg
, sdr
, 1);
432 DNSServiceRefDeallocate(sdr
);
436 sdr
->op
= reg_service_request
;
437 sdr
->process_reply
= callBack
? handle_regservice_response
: NULL
;
438 sdr
->app_callback
= callBack
;
439 sdr
->app_context
= context
;
446 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
447 return kDNSServiceErr_Unknown
;
451 static void handle_regservice_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
453 DNSServiceFlags flags
;
454 uint32_t interfaceIndex
;
455 DNSServiceErrorType errorCode
;
456 char name
[256], regtype
[256], domain
[256];
459 flags
= get_flags(&data
);
460 interfaceIndex
= get_long(&data
);
461 errorCode
= get_error_code(&data
);
462 get_string(&data
, name
, 256);
463 get_string(&data
, regtype
, 256);
464 get_string(&data
, domain
, 256);
465 ((DNSServiceRegisterReply
)sdr
->app_callback
)(sdr
, flags
, errorCode
, name
, regtype
, domain
, sdr
->app_context
);
468 DNSServiceErrorType DNSServiceEnumerateDomains
470 DNSServiceRef
*sdRef
,
471 const DNSServiceFlags flags
,
472 const uint32_t interfaceIndex
,
473 const DNSServiceDomainEnumReply callBack
,
477 char *msg
= NULL
, *ptr
;
481 DNSServiceErrorType err
;
484 if (!sdRef
) return kDNSServiceErr_BadParam
;
487 len
= sizeof(DNSServiceFlags
);
488 len
+= sizeof(uint32_t);
490 hdr
= create_hdr(enumeration_request
, &len
, &ptr
, 1);
491 if (!hdr
) goto error
;
494 put_flags(flags
, &ptr
);
495 put_long(interfaceIndex
, &ptr
);
497 sdr
= connect_to_server();
498 if (!sdr
) goto error
;
499 err
= deliver_request(msg
, sdr
, 1);
502 DNSServiceRefDeallocate(sdr
);
506 sdr
->op
= enumeration_request
;
507 sdr
->process_reply
= handle_enumeration_response
;
508 sdr
->app_callback
= callBack
;
509 sdr
->app_context
= context
;
515 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
516 return kDNSServiceErr_Unknown
;
520 static void handle_enumeration_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
522 DNSServiceFlags flags
;
523 uint32_t interfaceIndex
;
524 DNSServiceErrorType err
;
528 flags
= get_flags(&data
);
529 interfaceIndex
= get_long(&data
);
530 err
= get_error_code(&data
);
531 get_string(&data
, domain
, 256);
532 ((DNSServiceDomainEnumReply
)sdr
->app_callback
)(sdr
, flags
, interfaceIndex
, err
, domain
, sdr
->app_context
);
536 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
538 if (!sdRef
) return kDNSServiceErr_BadParam
;
539 *sdRef
= connect_to_server();
541 return kDNSServiceErr_Unknown
;
542 (*sdRef
)->op
= connection
;
543 (*sdRef
)->process_reply
= handle_regrecord_response
;
549 static void handle_regrecord_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
551 DNSServiceFlags flags
;
552 uint32_t interfaceIndex
;
553 DNSServiceErrorType errorCode
;
554 DNSRecordRef rref
= hdr
->client_context
.context
;
556 if (sdr
->op
!= connection
)
558 rref
->app_callback(rref
->sdr
, rref
, 0, kDNSServiceErr_Unknown
, rref
->app_context
);
561 flags
= get_flags(&data
);
562 interfaceIndex
= get_long(&data
);
563 errorCode
= get_error_code(&data
);
565 rref
->app_callback(rref
->sdr
, rref
, flags
, errorCode
, rref
->app_context
);
568 DNSServiceErrorType DNSServiceRegisterRecord
570 const DNSServiceRef sdRef
,
571 DNSRecordRef
*RecordRef
,
572 const DNSServiceFlags flags
,
573 const uint32_t interfaceIndex
,
574 const char *fullname
,
575 const uint16_t rrtype
,
576 const uint16_t rrclass
,
577 const uint16_t rdlen
,
580 const DNSServiceRegisterRecordReply callBack
,
584 char *msg
= NULL
, *ptr
;
586 ipc_msg_hdr
*hdr
= NULL
;
587 DNSServiceRef tmp
= NULL
;
588 DNSRecordRef rref
= NULL
;
590 if (!sdRef
|| sdRef
->op
!= connection
|| sdRef
->sockfd
< 0)
591 return kDNSServiceErr_BadReference
;
594 len
= sizeof(DNSServiceFlags
);
595 len
+= 2 * sizeof(uint32_t); // interfaceIndex, ttl
596 len
+= 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen
597 len
+= strlen(fullname
) + 1;
600 hdr
= create_hdr(reg_record_request
, &len
, &ptr
, 0);
601 if (!hdr
) goto error
;
603 put_flags(flags
, &ptr
);
604 put_long(interfaceIndex
, &ptr
);
605 put_string(fullname
, &ptr
);
606 put_short(rrtype
, &ptr
);
607 put_short(rrclass
, &ptr
);
608 put_short(rdlen
, &ptr
);
609 put_rdata(rdlen
, rdata
, &ptr
);
612 rref
= malloc(sizeof(_DNSRecordRef_t
));
613 if (!rref
) goto error
;
614 rref
->app_context
= context
;
615 rref
->app_callback
= callBack
;
616 rref
->record_index
= sdRef
->max_index
++;
619 hdr
->client_context
.context
= rref
;
620 hdr
->reg_index
= rref
->record_index
;
622 return deliver_request(msg
, sdRef
, 0);
625 if (rref
) free(rref
);
628 return kDNSServiceErr_Unknown
;
631 //sdRef returned by DNSServiceRegister()
632 DNSServiceErrorType DNSServiceAddRecord
634 const DNSServiceRef sdRef
,
635 DNSRecordRef
*RecordRef
,
636 const DNSServiceFlags flags
,
637 const uint16_t rrtype
,
638 const uint16_t rdlen
,
648 if (!sdRef
|| (sdRef
->op
!= reg_service_request
) || !RecordRef
)
649 return kDNSServiceErr_BadReference
;
652 len
+= 2 * sizeof(uint16_t); //rrtype, rdlen
654 len
+= sizeof(uint32_t);
655 len
+= sizeof(DNSServiceFlags
);
657 hdr
= create_hdr(add_record_request
, &len
, &ptr
, 0);
658 if (!hdr
) return kDNSServiceErr_Unknown
;
659 put_flags(flags
, &ptr
);
660 put_short(rrtype
, &ptr
);
661 put_short(rdlen
, &ptr
);
662 put_rdata(rdlen
, rdata
, &ptr
);
665 rref
= malloc(sizeof(_DNSRecordRef_t
));
666 if (!rref
) goto error
;
667 rref
->app_context
= NULL
;
668 rref
->app_callback
= NULL
;
669 rref
->record_index
= sdRef
->max_index
++;
672 hdr
->client_context
.context
= rref
;
673 hdr
->reg_index
= rref
->record_index
;
674 return deliver_request((char *)hdr
, sdRef
, 0);
678 if (rref
) free(rref
);
679 if (*RecordRef
) *RecordRef
= NULL
;
680 return kDNSServiceErr_Unknown
;
684 //DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord
685 DNSServiceErrorType DNSServiceUpdateRecord
687 const DNSServiceRef sdRef
,
688 DNSRecordRef RecordRef
,
689 const DNSServiceFlags flags
,
690 const uint16_t rdlen
,
699 if (!sdRef
|| !RecordRef
|| !sdRef
->max_index
)
700 return kDNSServiceErr_BadReference
;
702 len
+= sizeof(uint16_t);
704 len
+= sizeof(uint32_t);
705 len
+= sizeof(DNSServiceFlags
);
707 hdr
= create_hdr(update_record_request
, &len
, &ptr
, 0);
708 if (!hdr
) return kDNSServiceErr_Unknown
;
709 hdr
->reg_index
= RecordRef
? RecordRef
->record_index
: TXT_RECORD_INDEX
;
710 put_flags(flags
, &ptr
);
711 put_short(rdlen
, &ptr
);
712 put_rdata(rdlen
, rdata
, &ptr
);
714 return deliver_request((char *)hdr
, sdRef
, 0);
719 DNSServiceErrorType DNSServiceRemoveRecord
721 const DNSServiceRef sdRef
,
722 const DNSRecordRef RecordRef
,
723 const DNSServiceFlags flags
729 DNSServiceErrorType err
;
731 if (!sdRef
|| !RecordRef
|| !sdRef
->max_index
)
732 return kDNSServiceErr_BadReference
;
734 len
+= sizeof(flags
);
735 hdr
= create_hdr(remove_record_request
, &len
, &ptr
, 0);
736 if (!hdr
) return kDNSServiceErr_Unknown
;
737 hdr
->reg_index
= RecordRef
->record_index
;
738 put_flags(flags
, &ptr
);
739 err
= deliver_request((char *)hdr
, sdRef
, 0);
740 if (!err
) free(RecordRef
);
745 void DNSServiceReconfirmRecord
747 const DNSServiceFlags flags
,
748 const uint32_t interfaceIndex
,
749 const char *fullname
,
750 const uint16_t rrtype
,
751 const uint16_t rrclass
,
752 const uint16_t rdlen
,
761 len
= sizeof(DNSServiceFlags
);
762 len
+= sizeof(uint32_t);
763 len
+= strlen(fullname
) + 1;
764 len
+= 3 * sizeof(uint16_t);
766 tmp
= connect_to_server();
768 hdr
= create_hdr(reconfirm_record_request
, &len
, &ptr
, 1);
771 put_flags(flags
, &ptr
);
772 put_long(interfaceIndex
, &ptr
);
773 put_string(fullname
, &ptr
);
774 put_short(rrtype
, &ptr
);
775 put_short(rrclass
, &ptr
);
776 put_short(rdlen
, &ptr
);
777 put_rdata(rdlen
, rdata
, &ptr
);
778 my_write(tmp
->sockfd
, (char *)hdr
, len
);
779 DNSServiceRefDeallocate(tmp
);
783 int DNSServiceConstructFullName
786 const char *service
, /* may be NULL */
794 const char *s
= service
;
795 const char *r
= regtype
;
796 const char *d
= domain
;
803 if (c
== '.' || (c
== '\\')) *fn
++ = '\\'; // escape dot and backslash literals
804 else if (c
<= ' ') // escape non-printable characters
807 *fn
++ = (char) ('0' + (c
/ 100));
808 *fn
++ = (char) ('0' + (c
/ 10) % 10);
809 c
= (u_char
)('0' + (c
% 10));
816 if (!regtype
) return -1;
817 len
= strlen(regtype
);
818 if (domain_ends_in_dot(regtype
)) len
--;
819 if (len
< 4) return -1; // regtype must end in _udp or _tcp
820 if (strncmp((regtype
+ len
- 4), "_tcp", 4) && strncmp((regtype
+ len
- 4), "_udp", 4)) return -1;
823 if (!domain_ends_in_dot(regtype
)) *fn
++ = '.';
825 if (!domain
) return -1;
826 len
= strlen(domain
);
830 if (!domain_ends_in_dot(domain
)) *fn
++ = '.';
835 static int domain_ends_in_dot(const char *dom
)
837 while(*dom
&& *(dom
+ 1))
839 if (*dom
== '\\') // advance past escaped byte sequence
841 if (*(dom
+ 1) >= '0' && *(dom
+ 1) <= '9') dom
+= 4;
844 else dom
++; // else read one character
846 return (*dom
== '.');
851 // return a connected service ref (deallocate with DNSServiceRefDeallocate)
852 static DNSServiceRef
connect_to_server(void)
854 struct sockaddr_un saddr
;
857 sdr
= malloc(sizeof(_DNSServiceRef_t
));
858 if (!sdr
) return NULL
;
860 if ((sdr
->sockfd
= socket(AF_LOCAL
, SOCK_STREAM
, 0)) < 0)
866 saddr
.sun_family
= AF_LOCAL
;
867 strcpy(saddr
.sun_path
, MDNS_UDS_SERVERPATH
);
868 if (connect(sdr
->sockfd
, (struct sockaddr
*)&saddr
, sizeof(saddr
)) < 0)
879 int my_write(int sd
, char *buf
, int len
)
881 if (send(sd
, buf
, len
, MSG_WAITALL
) != len
) return -1;
886 // read len bytes. return 0 on success, -1 on error
887 int my_read(int sd
, char *buf
, int len
)
889 if (recv(sd
, buf
, len
, MSG_WAITALL
) != len
) return -1;
894 DNSServiceErrorType
deliver_request(void *msg
, DNSServiceRef sdr
, int reuse_sd
)
896 ipc_msg_hdr
*hdr
= msg
;
898 struct sockaddr_un caddr
, daddr
; // (client and daemon address structs)
900 int listenfd
= -1, errsd
= -1, len
;
901 DNSServiceErrorType err
= kDNSServiceErr_Unknown
;
903 if (!hdr
|| sdr
->sockfd
< 0) return kDNSServiceErr_Unknown
;
907 // setup temporary error socket
908 if ((listenfd
= socket(AF_LOCAL
, SOCK_STREAM
, 0)) < 0)
911 bzero(&caddr
, sizeof(caddr
));
912 caddr
.sun_family
= AF_LOCAL
;
913 caddr
.sun_len
= sizeof(struct sockaddr_un
);
914 path
= (char *)msg
+ sizeof(ipc_msg_hdr
);
915 strcpy(caddr
.sun_path
, path
);
917 if (bind(listenfd
, (struct sockaddr
*)&caddr
, sizeof(caddr
)) < 0)
926 if (my_write(sdr
->sockfd
, msg
, hdr
->datalen
+ sizeof(ipc_msg_hdr
)) < 0)
931 if (reuse_sd
) errsd
= sdr
->sockfd
;
935 errsd
= accept(listenfd
, (struct sockaddr
*)&daddr
, &len
);
936 if (errsd
< 0) goto cleanup
;
939 len
= recv(errsd
, &err
, sizeof(err
), MSG_WAITALL
);
940 if (len
!= sizeof(err
))
942 err
= kDNSServiceErr_Unknown
;
945 if (!reuse_sd
&& listenfd
> 0) close(listenfd
);
946 if (!reuse_sd
&& errsd
> 0) close(errsd
);
947 if (!reuse_sd
&& path
) unlink(path
);
956 * allocate and initialize an ipc message header. value of len should initially be the
957 * length of the data, and is set to the value of the data plus the header. data_start
958 * is set to point to the beginning of the data section. reuse_socket should be non-zero
959 * for calls that can receive an immediate error return value on their primary socket.
960 * if zero, the path to a control socket is appended at the beginning of the message buffer.
961 * data_start is set past this string.
964 static ipc_msg_hdr
*create_hdr(int op
, int *len
, char **data_start
, int reuse_socket
)
974 if (gettimeofday(&time
, NULL
) < 0) return NULL
;
975 sprintf(ctrl_path
, "%s%d-%.3x-%.6u", CTL_PATH_PREFIX
, (int)getpid(),
976 time
.tv_sec
& 0xFFF, time
.tv_usec
);
978 *len
+= strlen(ctrl_path
) + 1;
983 *len
+= sizeof(ipc_msg_hdr
);
985 // write message to buffer
987 if (!msg
) return NULL
;
991 hdr
->datalen
= datalen
;
992 hdr
->version
= VERSION
;
993 hdr
->op
.request_op
= op
;
994 if (reuse_socket
) hdr
->flags
|= IPC_FLAGS_REUSE_SOCKET
;
995 *data_start
= msg
+ sizeof(ipc_msg_hdr
);
996 if (!reuse_socket
) put_string(ctrl_path
, data_start
);