2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.2 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include "dnssd_ipc.h"
29 #define CTL_PATH_PREFIX "/tmp/dnssd_clippath."
30 // error socket (if needed) is named "dnssd_clipath.[pid].xxx:n" where xxx are the
31 // last 3 digits of the time (in seconds) and n is the 6-digit microsecond time
33 // general utility functions
34 static DNSServiceRef
connect_to_server(void);
35 DNSServiceErrorType
deliver_request(void *msg
, DNSServiceRef sdr
, int reuse_sd
);
36 static ipc_msg_hdr
*create_hdr(int op
, int *len
, char **data_start
, int reuse_socket
);
37 static int my_read(int sd
, char *buf
, int len
);
38 static int my_write(int sd
, char *buf
, int len
);
39 static int domain_ends_in_dot(const char *dom
);
40 // server response handlers
41 static void handle_query_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *msg
);
42 static void handle_browse_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
43 static void handle_regservice_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
44 static void handle_regrecord_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
45 static void handle_enumeration_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
46 static void handle_resolve_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
);
48 typedef struct _DNSServiceRef_t
50 int sockfd
; // connected socket between client and daemon
51 int op
; // request/reply_op_t
52 process_reply_callback process_reply
;
55 uint32_t max_index
; //largest assigned record index - 0 if no additl. recs registered
58 typedef struct _DNSRecordRef_t
61 DNSServiceRegisterRecordReply app_callback
;
63 int record_index
; // index is unique to the ServiceDiscoveryRef
70 int DNSServiceRefSockFD(DNSServiceRef sdRef
)
72 if (!sdRef
) return -1;
76 // handle reply from server, calling application client callback. If there is no reply
77 // from the daemon on the socket contained in sdRef, the call will block.
78 DNSServiceErrorType
DNSServiceProcessResult(DNSServiceRef sdRef
)
83 if (!sdRef
|| sdRef
->sockfd
< 0 || !sdRef
->process_reply
)
84 return kDNSServiceErr_BadReference
;
86 if (my_read(sdRef
->sockfd
, (void *)&hdr
, sizeof(hdr
)) < 0)
87 return kDNSServiceErr_Unknown
;
88 if (hdr
.version
!= VERSION
)
89 return kDNSServiceErr_Incompatible
;
90 data
= malloc(hdr
.datalen
);
91 if (!data
) return kDNSServiceErr_NoMemory
;
92 if (my_read(sdRef
->sockfd
, data
, hdr
.datalen
) < 0)
93 return kDNSServiceErr_Unknown
;
94 sdRef
->process_reply(sdRef
, &hdr
, data
);
96 return kDNSServiceErr_NoError
;
100 void DNSServiceRefDeallocate(DNSServiceRef sdRef
)
103 if (sdRef
->sockfd
> 0) close(sdRef
->sockfd
);
108 DNSServiceErrorType DNSServiceResolve
110 DNSServiceRef
*sdRef
,
111 const DNSServiceFlags flags
,
112 const uint32_t interfaceIndex
,
116 const DNSServiceResolveReply callBack
,
120 char *msg
= NULL
, *ptr
;
124 DNSServiceErrorType err
;
126 if (!sdRef
) return kDNSServiceErr_BadParam
;
129 // calculate total message length
131 len
+= sizeof(interfaceIndex
);
132 len
+= strlen(name
) + 1;
133 len
+= strlen(regtype
) + 1;
134 len
+= strlen(domain
) + 1;
136 hdr
= create_hdr(resolve_request
, &len
, &ptr
, 1);
137 if (!hdr
) goto error
;
140 put_flags(flags
, &ptr
);
141 put_long(interfaceIndex
, &ptr
);
142 put_string(name
, &ptr
);
143 put_string(regtype
, &ptr
);
144 put_string(domain
, &ptr
);
146 sdr
= connect_to_server();
147 if (!sdr
) goto error
;
148 err
= deliver_request(msg
, sdr
, 1);
151 DNSServiceRefDeallocate(sdr
);
154 sdr
->op
= resolve_request
;
155 sdr
->process_reply
= handle_resolve_response
;
156 sdr
->app_callback
= callBack
;
157 sdr
->app_context
= context
;
164 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
165 return kDNSServiceErr_Unknown
;
169 static void handle_resolve_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
171 DNSServiceFlags flags
;
172 char fullname
[kDNSServiceMaxDomainName
];
173 char target
[kDNSServiceMaxDomainName
];
174 uint16_t port
, txtlen
;
176 DNSServiceErrorType err
;
181 flags
= get_flags(&data
);
182 ifi
= get_long(&data
);
183 err
= get_error_code(&data
);
184 get_string(&data
, fullname
, kDNSServiceMaxDomainName
);
185 get_string(&data
, target
, kDNSServiceMaxDomainName
);
186 port
= get_short(&data
);
187 txtlen
= get_short(&data
);
188 txtrecord
= get_rdata(&data
, txtlen
);
190 ((DNSServiceResolveReply
)sdr
->app_callback
)(sdr
, flags
, ifi
, err
, fullname
, target
, port
, txtlen
, txtrecord
, sdr
->app_context
);
196 DNSServiceErrorType DNSServiceQueryRecord
198 DNSServiceRef
*sdRef
,
199 const DNSServiceFlags flags
,
200 const uint32_t interfaceIndex
,
202 const uint16_t rrtype
,
203 const uint16_t rrclass
,
204 const DNSServiceQueryRecordReply callBack
,
208 char *msg
= NULL
, *ptr
;
212 DNSServiceErrorType err
;
214 if (!sdRef
) return kDNSServiceErr_BadParam
;
217 if (!name
) name
= "\0";
219 // calculate total message length
221 len
+= sizeof(uint32_t); //interfaceIndex
222 len
+= strlen(name
) + 1;
223 len
+= 2 * sizeof(uint16_t); // rrtype, rrclass
225 hdr
= create_hdr(query_request
, &len
, &ptr
, 1);
226 if (!hdr
) goto error
;
229 put_flags(flags
, &ptr
);
230 put_long(interfaceIndex
, &ptr
);
231 put_string(name
, &ptr
);
232 put_short(rrtype
, &ptr
);
233 put_short(rrclass
, &ptr
);
235 sdr
= connect_to_server();
236 if (!sdr
) goto error
;
237 err
= deliver_request(msg
, sdr
, 1);
240 DNSServiceRefDeallocate(sdr
);
244 sdr
->op
= query_request
;
245 sdr
->process_reply
= handle_query_response
;
246 sdr
->app_callback
= callBack
;
247 sdr
->app_context
= context
;
253 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
254 return kDNSServiceErr_Unknown
;
258 static void handle_query_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
260 DNSServiceFlags flags
;
261 uint32_t interfaceIndex
, ttl
;
262 DNSServiceErrorType errorCode
;
264 uint16_t rrtype
, rrclass
, rdlen
;
268 flags
= get_flags(&data
);
269 interfaceIndex
= get_long(&data
);
270 errorCode
= get_error_code(&data
);
271 (get_string(&data
, name
, 256) < 0);
272 rrtype
= get_short(&data
);
273 rrclass
= get_short(&data
);
274 rdlen
= get_short(&data
);
275 rdata
= get_rdata(&data
, rdlen
);
276 ttl
= get_long(&data
);
278 ((DNSServiceQueryRecordReply
)sdr
->app_callback
)(sdr
, flags
, interfaceIndex
, errorCode
, name
, rrtype
, rrclass
,
279 rdlen
, rdata
, ttl
, sdr
->app_context
);
283 DNSServiceErrorType DNSServiceBrowse
285 DNSServiceRef
*sdRef
,
286 const DNSServiceFlags flags
,
287 const uint32_t interfaceIndex
,
290 const DNSServiceBrowseReply callBack
,
294 char *msg
= NULL
, *ptr
;
298 DNSServiceErrorType err
;
300 if (!sdRef
) return kDNSServiceErr_BadParam
;
303 if (!domain
) domain
= "";
306 len
+= sizeof(interfaceIndex
);
307 len
+= strlen(regtype
) + 1;
308 len
+= strlen(domain
) + 1;
310 hdr
= create_hdr(browse_request
, &len
, &ptr
, 1);
311 if (!hdr
) goto error
;
313 put_flags(flags
, &ptr
);
314 put_long(interfaceIndex
, &ptr
);
315 put_string(regtype
, &ptr
);
316 put_string(domain
, &ptr
);
318 sdr
= connect_to_server();
319 if (!sdr
) goto error
;
320 err
= deliver_request(msg
, sdr
, 1);
323 DNSServiceRefDeallocate(sdr
);
326 sdr
->op
= browse_request
;
327 sdr
->process_reply
= handle_browse_response
;
328 sdr
->app_callback
= callBack
;
329 sdr
->app_context
= context
;
335 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
336 return kDNSServiceErr_Unknown
;
342 static void handle_browse_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
344 DNSServiceFlags flags
;
345 uint32_t interfaceIndex
;
346 DNSServiceErrorType errorCode
;
347 char replyName
[256], replyType
[256], replyDomain
[256];
350 flags
= get_flags(&data
);
351 interfaceIndex
= get_long(&data
);
352 errorCode
= get_error_code(&data
);
353 get_string(&data
, replyName
, 256);
354 get_string(&data
, replyType
, 256);
355 get_string(&data
, replyDomain
, 256);
356 ((DNSServiceBrowseReply
)sdr
->app_callback
)(sdr
, flags
, interfaceIndex
, errorCode
, replyName
, replyType
, replyDomain
, sdr
->app_context
);
360 DNSServiceErrorType DNSServiceRegister
362 DNSServiceRef
*sdRef
,
363 const DNSServiceFlags flags
,
364 const uint32_t interfaceIndex
,
370 const uint16_t txtLen
,
371 const void *txtRecord
,
372 const DNSServiceRegisterReply callBack
,
376 char *msg
= NULL
, *ptr
;
380 DNSServiceErrorType err
;
382 if (!sdRef
) return kDNSServiceErr_BadParam
;
385 if (!name
) name
= "";
386 if (!regtype
) return kDNSServiceErr_BadParam
;
387 if (!domain
) domain
= "";
388 if (!host
) host
= "";
389 if (!txtRecord
) (char *)txtRecord
= "";
391 // auto-name must also have auto-rename
392 if (!name
[0] && (flags
& kDNSServiceFlagsNoAutoRename
))
393 return kDNSServiceErr_BadParam
;
395 // no callback must have auto-name
396 if (!callBack
&& name
[0]) return kDNSServiceErr_BadParam
;
398 len
= sizeof(DNSServiceFlags
);
399 len
+= sizeof(uint32_t); // interfaceIndex
400 len
+= strlen(name
) + strlen(regtype
) + strlen(domain
) + strlen(host
) + 4;
401 len
+= 2 * sizeof(uint16_t); // port, txtLen
404 hdr
= create_hdr(reg_service_request
, &len
, &ptr
, 1);
405 if (!hdr
) goto error
;
406 if (!callBack
) hdr
->flags
|= IPC_FLAGS_NOREPLY
;
408 put_flags(flags
, &ptr
);
409 put_long(interfaceIndex
, &ptr
);
410 put_string(name
, &ptr
);
411 put_string(regtype
, &ptr
);
412 put_string(domain
, &ptr
);
413 put_string(host
, &ptr
);
414 put_short(port
, &ptr
);
415 put_short(txtLen
, &ptr
);
416 put_rdata(txtLen
, txtRecord
, &ptr
);
418 sdr
= connect_to_server();
419 if (!sdr
) goto error
;
420 err
= deliver_request(msg
, sdr
, 1);
423 DNSServiceRefDeallocate(sdr
);
427 sdr
->op
= reg_service_request
;
428 sdr
->process_reply
= callBack
? handle_regservice_response
: NULL
;
429 sdr
->app_callback
= callBack
;
430 sdr
->app_context
= context
;
437 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
438 return kDNSServiceErr_Unknown
;
442 static void handle_regservice_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
444 DNSServiceFlags flags
;
445 uint32_t interfaceIndex
;
446 DNSServiceErrorType errorCode
;
447 char name
[256], regtype
[256], domain
[256];
450 flags
= get_flags(&data
);
451 interfaceIndex
= get_long(&data
);
452 errorCode
= get_error_code(&data
);
453 get_string(&data
, name
, 256);
454 get_string(&data
, regtype
, 256);
455 get_string(&data
, domain
, 256);
456 ((DNSServiceRegisterReply
)sdr
->app_callback
)(sdr
, flags
, errorCode
, name
, regtype
, domain
, sdr
->app_context
);
459 DNSServiceErrorType DNSServiceEnumerateDomains
461 DNSServiceRef
*sdRef
,
462 const DNSServiceFlags flags
,
463 const uint32_t interfaceIndex
,
464 const DNSServiceDomainEnumReply callBack
,
468 char *msg
= NULL
, *ptr
;
472 DNSServiceErrorType err
;
475 if (!sdRef
) return kDNSServiceErr_BadParam
;
478 len
= sizeof(DNSServiceFlags
);
479 len
+= sizeof(uint32_t);
481 hdr
= create_hdr(enumeration_request
, &len
, &ptr
, 1);
482 if (!hdr
) goto error
;
485 put_flags(flags
, &ptr
);
486 put_long(interfaceIndex
, &ptr
);
488 sdr
= connect_to_server();
489 if (!sdr
) goto error
;
490 err
= deliver_request(msg
, sdr
, 1);
493 DNSServiceRefDeallocate(sdr
);
497 sdr
->op
= enumeration_request
;
498 sdr
->process_reply
= handle_enumeration_response
;
499 sdr
->app_callback
= callBack
;
500 sdr
->app_context
= context
;
506 if (*sdRef
) { free(*sdRef
); *sdRef
= NULL
; }
507 return kDNSServiceErr_Unknown
;
511 static void handle_enumeration_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
513 DNSServiceFlags flags
;
514 uint32_t interfaceIndex
;
515 DNSServiceErrorType err
;
519 flags
= get_flags(&data
);
520 interfaceIndex
= get_long(&data
);
521 err
= get_error_code(&data
);
522 get_string(&data
, domain
, 256);
523 ((DNSServiceDomainEnumReply
)sdr
->app_callback
)(sdr
, flags
, interfaceIndex
, err
, domain
, sdr
->app_context
);
527 DNSServiceErrorType
DNSServiceCreateConnection(DNSServiceRef
*sdRef
)
529 if (!sdRef
) return kDNSServiceErr_BadParam
;
530 *sdRef
= connect_to_server();
532 return kDNSServiceErr_Unknown
;
533 (*sdRef
)->op
= connection
;
534 (*sdRef
)->process_reply
= handle_regrecord_response
;
540 static void handle_regrecord_response(DNSServiceRef sdr
, ipc_msg_hdr
*hdr
, char *data
)
542 DNSServiceFlags flags
;
543 uint32_t interfaceIndex
;
544 DNSServiceErrorType errorCode
;
545 DNSRecordRef rref
= hdr
->client_context
.context
;
547 if (sdr
->op
!= connection
)
549 rref
->app_callback(rref
->sdr
, rref
, 0, kDNSServiceErr_Unknown
, rref
->app_context
);
552 flags
= get_flags(&data
);
553 interfaceIndex
= get_long(&data
);
554 errorCode
= get_error_code(&data
);
556 rref
->app_callback(rref
->sdr
, rref
, flags
, errorCode
, rref
->app_context
);
559 DNSServiceErrorType DNSServiceRegisterRecord
561 const DNSServiceRef sdRef
,
562 DNSRecordRef
*RecordRef
,
563 const DNSServiceFlags flags
,
564 const uint32_t interfaceIndex
,
565 const char *fullname
,
566 const uint16_t rrtype
,
567 const uint16_t rrclass
,
568 const uint16_t rdlen
,
571 const DNSServiceRegisterRecordReply callBack
,
575 char *msg
= NULL
, *ptr
;
577 ipc_msg_hdr
*hdr
= NULL
;
578 DNSServiceRef tmp
= NULL
;
579 DNSRecordRef rref
= NULL
;
581 if (!sdRef
|| sdRef
->op
!= connection
|| sdRef
->sockfd
< 0)
582 return kDNSServiceErr_BadReference
;
585 len
= sizeof(DNSServiceFlags
);
586 len
+= 2 * sizeof(uint32_t); // interfaceIndex, ttl
587 len
+= 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen
588 len
+= strlen(fullname
) + 1;
591 hdr
= create_hdr(reg_record_request
, &len
, &ptr
, 0);
592 if (!hdr
) goto error
;
594 put_flags(flags
, &ptr
);
595 put_long(interfaceIndex
, &ptr
);
596 put_string(fullname
, &ptr
);
597 put_short(rrtype
, &ptr
);
598 put_short(rrclass
, &ptr
);
599 put_short(rdlen
, &ptr
);
600 put_rdata(rdlen
, rdata
, &ptr
);
603 rref
= malloc(sizeof(_DNSRecordRef_t
));
604 if (!rref
) goto error
;
605 rref
->app_context
= context
;
606 rref
->app_callback
= callBack
;
607 rref
->record_index
= sdRef
->max_index
++;
610 hdr
->client_context
.context
= rref
;
611 hdr
->reg_index
= rref
->record_index
;
613 return deliver_request(msg
, sdRef
, 0);
616 if (rref
) free(rref
);
619 return kDNSServiceErr_Unknown
;
622 //sdRef returned by DNSServiceRegister()
623 DNSServiceErrorType DNSServiceAddRecord
625 const DNSServiceRef sdRef
,
626 DNSRecordRef
*RecordRef
,
627 const DNSServiceFlags flags
,
628 const uint16_t rrtype
,
629 const uint16_t rdlen
,
639 if (!sdRef
|| (sdRef
->op
!= reg_service_request
) || !RecordRef
)
640 return kDNSServiceErr_BadReference
;
643 len
+= 2 * sizeof(uint16_t); //rrtype, rdlen
645 len
+= sizeof(uint32_t);
646 len
+= sizeof(DNSServiceFlags
);
648 hdr
= create_hdr(add_record_request
, &len
, &ptr
, 0);
649 if (!hdr
) return kDNSServiceErr_Unknown
;
650 put_flags(flags
, &ptr
);
651 put_short(rrtype
, &ptr
);
652 put_short(rdlen
, &ptr
);
653 put_rdata(rdlen
, rdata
, &ptr
);
656 rref
= malloc(sizeof(_DNSRecordRef_t
));
657 if (!rref
) goto error
;
658 rref
->app_context
= NULL
;
659 rref
->app_callback
= NULL
;
660 rref
->record_index
= sdRef
->max_index
++;
663 hdr
->client_context
.context
= rref
;
664 hdr
->reg_index
= rref
->record_index
;
665 return deliver_request((char *)hdr
, sdRef
, 0);
669 if (rref
) free(rref
);
670 if (*RecordRef
) *RecordRef
= NULL
;
671 return kDNSServiceErr_Unknown
;
675 //DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord
676 DNSServiceErrorType DNSServiceUpdateRecord
678 const DNSServiceRef sdRef
,
679 DNSRecordRef RecordRef
,
680 const DNSServiceFlags flags
,
681 const uint16_t rdlen
,
691 return kDNSServiceErr_BadReference
;
693 len
+= sizeof(uint16_t);
695 len
+= sizeof(uint32_t);
696 len
+= sizeof(DNSServiceFlags
);
698 hdr
= create_hdr(update_record_request
, &len
, &ptr
, 0);
699 if (!hdr
) return kDNSServiceErr_Unknown
;
700 hdr
->reg_index
= RecordRef
? RecordRef
->record_index
: TXT_RECORD_INDEX
;
701 put_flags(flags
, &ptr
);
702 put_short(rdlen
, &ptr
);
703 put_rdata(rdlen
, rdata
, &ptr
);
705 return deliver_request((char *)hdr
, sdRef
, 0);
710 DNSServiceErrorType DNSServiceRemoveRecord
712 const DNSServiceRef sdRef
,
713 const DNSRecordRef RecordRef
,
714 const DNSServiceFlags flags
720 DNSServiceErrorType err
;
722 if (!sdRef
|| !RecordRef
|| !sdRef
->max_index
)
723 return kDNSServiceErr_BadReference
;
725 len
+= sizeof(flags
);
726 hdr
= create_hdr(remove_record_request
, &len
, &ptr
, 0);
727 if (!hdr
) return kDNSServiceErr_Unknown
;
728 hdr
->reg_index
= RecordRef
->record_index
;
729 put_flags(flags
, &ptr
);
730 err
= deliver_request((char *)hdr
, sdRef
, 0);
731 if (!err
) free(RecordRef
);
736 void DNSServiceReconfirmRecord
738 const DNSServiceFlags flags
,
739 const uint32_t interfaceIndex
,
740 const char *fullname
,
741 const uint16_t rrtype
,
742 const uint16_t rrclass
,
743 const uint16_t rdlen
,
752 len
= sizeof(DNSServiceFlags
);
753 len
+= sizeof(uint32_t);
754 len
+= strlen(fullname
) + 1;
755 len
+= 3 * sizeof(uint16_t);
757 tmp
= connect_to_server();
759 hdr
= create_hdr(reconfirm_record_request
, &len
, &ptr
, 1);
762 put_flags(flags
, &ptr
);
763 put_long(interfaceIndex
, &ptr
);
764 put_string(fullname
, &ptr
);
765 put_short(rrtype
, &ptr
);
766 put_short(rrclass
, &ptr
);
767 put_short(rdlen
, &ptr
);
768 put_rdata(rdlen
, rdata
, &ptr
);
769 my_write(tmp
->sockfd
, (char *)hdr
, len
);
770 DNSServiceRefDeallocate(tmp
);
774 int DNSServiceConstructFullName
777 const char *service
, /* may be NULL */
785 const char *s
= service
;
786 const char *r
= regtype
;
787 const char *d
= domain
;
794 if (c
== '.' || (c
== '\\')) *fn
++ = '\\'; // escape dot and backslash literals
795 else if (c
<= ' ') // escape non-printable characters
798 *fn
++ = (char) ('0' + (c
/ 100));
799 *fn
++ = (char) ('0' + (c
/ 10) % 10);
800 c
= (u_char
)('0' + (c
% 10));
807 if (!regtype
) return -1;
808 len
= strlen(regtype
);
809 if (domain_ends_in_dot(regtype
)) len
--;
810 if (len
< 4) return -1; // regtype must end in _udp or _tcp
811 if (strncmp((regtype
+ len
- 4), "_tcp", 4) && strncmp((regtype
+ len
- 4), "_udp", 4)) return -1;
814 if (!domain_ends_in_dot(regtype
)) *fn
++ = '.';
816 if (!domain
) return -1;
817 len
= strlen(domain
);
821 if (!domain_ends_in_dot(domain
)) *fn
++ = '.';
826 static int domain_ends_in_dot(const char *dom
)
828 while(*dom
&& *(dom
+ 1))
830 if (*dom
== '\\') // advance past escaped byte sequence
832 if (*(dom
+ 1) >= '0' && *(dom
+ 1) <= '9') dom
+= 4;
835 else dom
++; // else read one character
837 return (*dom
== '.');
842 // return a connected service ref (deallocate with DNSServiceRefDeallocate)
843 static DNSServiceRef
connect_to_server(void)
845 struct sockaddr_un saddr
;
848 sdr
= malloc(sizeof(_DNSServiceRef_t
));
849 if (!sdr
) return NULL
;
851 if ((sdr
->sockfd
= socket(AF_LOCAL
, SOCK_STREAM
, 0)) < 0)
857 saddr
.sun_family
= AF_LOCAL
;
858 strcpy(saddr
.sun_path
, MDNS_UDS_SERVERPATH
);
859 if (connect(sdr
->sockfd
, (struct sockaddr
*)&saddr
, sizeof(saddr
)) < 0)
870 int my_write(int sd
, char *buf
, int len
)
872 if (send(sd
, buf
, len
, MSG_WAITALL
) != len
) return -1;
877 // read len bytes. return 0 on success, -1 on error
878 int my_read(int sd
, char *buf
, int len
)
880 if (recv(sd
, buf
, len
, MSG_WAITALL
) != len
) return -1;
885 DNSServiceErrorType
deliver_request(void *msg
, DNSServiceRef sdr
, int reuse_sd
)
887 ipc_msg_hdr
*hdr
= msg
;
889 struct sockaddr_un caddr
, daddr
; // (client and daemon address structs)
891 int listenfd
= -1, errsd
= -1, len
;
892 DNSServiceErrorType err
= kDNSServiceErr_Unknown
;
894 if (!hdr
|| sdr
->sockfd
< 0) return kDNSServiceErr_Unknown
;
898 // setup temporary error socket
899 if ((listenfd
= socket(AF_LOCAL
, SOCK_STREAM
, 0)) < 0)
902 bzero(&caddr
, sizeof(caddr
));
903 caddr
.sun_family
= AF_LOCAL
;
904 caddr
.sun_len
= sizeof(struct sockaddr_un
);
905 path
= (char *)msg
+ sizeof(ipc_msg_hdr
);
906 strcpy(caddr
.sun_path
, path
);
908 if (bind(listenfd
, (struct sockaddr
*)&caddr
, sizeof(caddr
)) < 0)
917 if (my_write(sdr
->sockfd
, msg
, hdr
->datalen
+ sizeof(ipc_msg_hdr
)) < 0)
922 if (reuse_sd
) errsd
= sdr
->sockfd
;
926 errsd
= accept(listenfd
, (struct sockaddr
*)&daddr
, &len
);
927 if (errsd
< 0) goto cleanup
;
930 len
= recv(errsd
, &err
, sizeof(err
), MSG_WAITALL
);
931 if (len
!= sizeof(err
))
933 err
= kDNSServiceErr_Unknown
;
936 if (!reuse_sd
&& listenfd
> 0) close(listenfd
);
937 if (!reuse_sd
&& errsd
> 0) close(errsd
);
938 if (!reuse_sd
&& path
) unlink(path
);
947 * allocate and initialize an ipc message header. value of len should initially be the
948 * length of the data, and is set to the value of the data plus the header. data_start
949 * is set to point to the beginning of the data section. reuse_socket should be non-zero
950 * for calls that can receive an immediate error return value on their primary socket.
951 * if zero, the path to a control socket is appended at the beginning of the message buffer.
952 * data_start is set past this string.
955 static ipc_msg_hdr
*create_hdr(int op
, int *len
, char **data_start
, int reuse_socket
)
965 if (gettimeofday(&time
, NULL
) < 0) return NULL
;
966 sprintf(ctrl_path
, "%s%d-%.3x-%.6u", CTL_PATH_PREFIX
, (int)getpid(),
967 time
.tv_sec
& 0xFFF, time
.tv_usec
);
969 *len
+= strlen(ctrl_path
) + 1;
974 *len
+= sizeof(ipc_msg_hdr
);
976 // write message to buffer
978 if (!msg
) return NULL
;
982 hdr
->datalen
= datalen
;
983 hdr
->version
= VERSION
;
984 hdr
->op
.request_op
= op
;
985 if (reuse_socket
) hdr
->flags
|= IPC_FLAGS_REUSE_SOCKET
;
986 *data_start
= msg
+ sizeof(ipc_msg_hdr
);
987 if (!reuse_socket
) put_string(ctrl_path
, data_start
);