577 syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect()-> No of tries: %d", NumTries);
578 sleep(1); // Sleep a bit, then try again
579 }
580 else
581 {
582 syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect() failed path:%s Socket:%d Err:%d Errno:%d %s",
583 uds_serverpath, sdr->sockfd, err, dnssd_errno, dnssd_strerror(dnssd_errno));
584 dnssd_close(sdr->sockfd);
585 FreeDNSServiceOp(sdr);
586 return kDNSServiceErr_ServiceNotRunning;
587 }
588 }
589 //printf("ConnectToServer opened socket %d\n", sdr->sockfd);
590 }
591
592 *ref = sdr;
593 return kDNSServiceErr_NoError;
594 }
595
596 #define deliver_request_bailout(MSG) \
597 do { syslog(LOG_WARNING, "dnssd_clientstub deliver_request: %s failed %d (%s)", (MSG), dnssd_errno, dnssd_strerror(dnssd_errno)); goto cleanup; } while(0)
598
599 static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
600 {
601 uint32_t datalen = hdr->datalen; // We take a copy here because we're going to convert hdr->datalen to network byte order
602 #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
603 char *const data = (char *)hdr + sizeof(ipc_msg_hdr);
604 #endif
605 dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
606 DNSServiceErrorType err = kDNSServiceErr_Unknown; // Default for the "goto cleanup" cases
607 int MakeSeparateReturnSocket = 0;
608
609 // Note: need to check hdr->op, not sdr->op.
610 // hdr->op contains the code for the specific operation we're currently doing, whereas sdr->op
611 // contains the original parent DNSServiceOp (e.g. for an add_record_request, hdr->op will be
612 // add_record_request but the parent sdr->op will be connection_request or reg_service_request)
613 if (sdr->primary ||
614 hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request)
615 MakeSeparateReturnSocket = 1;
616
617 if (!DNSServiceRefValid(sdr))
619 if (hdr)
620 free(hdr);
621 syslog(LOG_WARNING, "dnssd_clientstub deliver_request: invalid DNSServiceRef %p %08X %08X", sdr, sdr->sockfd, sdr->validator);
622 return kDNSServiceErr_BadReference;
623 }
624
625 if (!hdr)
626 {
627 syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr");
628 return kDNSServiceErr_Unknown;
629 }
630
631 if (MakeSeparateReturnSocket)
632 {
633 #if defined(USE_TCP_LOOPBACK)
634 {
635 union { uint16_t s; u_char b[2]; } port;
636 dnssd_sockaddr_t caddr;
637 dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
638 listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
639 if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("TCP socket");
640
641 caddr.sin_family = AF_INET;
642 caddr.sin_port = 0;
643 caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
644 if (bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)) < 0) deliver_request_bailout("TCP bind");
645 if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) deliver_request_bailout("TCP getsockname");
646 if (listen(listenfd, 1) < 0) deliver_request_bailout("TCP listen");
647 port.s = caddr.sin_port;
648 data[0] = port.b[0]; // don't switch the byte order, as the
649 data[1] = port.b[1]; // daemon expects it in network byte order
650 }
651 #elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
652 {
653 mode_t mask;
654 int bindresult;
655 dnssd_sockaddr_t caddr;
656 listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
657 if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket");
658
659 caddr.sun_family = AF_LOCAL;
660 // According to Stevens (section 3.2), there is no portable way to
661 // determine whether sa_len is defined on a particular platform.
662 #ifndef NOT_HAVE_SA_LEN
663 caddr.sun_len = sizeof(struct sockaddr_un);
664 #endif
665 strcpy(caddr.sun_path, data);
666 mask = umask(0);
667 bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
668 umask(mask);
669 if (bindresult < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET bind");
670 if (listen(listenfd, 1) < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen");
671 }
672 #else
673 {
674 dnssd_sock_t sp[2];
675 if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) deliver_request_bailout("socketpair");
676 else
677 {
678 errsd = sp[0]; // We'll read our four-byte error code from sp[0]
679 listenfd = sp[1]; // We'll send sp[1] to the daemon
680 #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
681 {
682 int defunct = 1;
683 if (setsockopt(errsd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
684 syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
685 }
686 #endif
687 }
688 }
689 #endif
690 }
691
692 #if !defined(USE_TCP_LOOPBACK) && !defined(USE_NAMED_ERROR_RETURN_SOCKET)
693 // If we're going to make a separate error return socket, and pass it to the daemon
694 // using sendmsg, then we'll hold back one data byte to go with it.
695 // On some versions of Unix (including Leopard) sending a control message without
721 // in the case of DEFUNCT sockets
722 syslog(LOG_INFO, "dnssd_clientstub deliver_request ERROR: write_all(%d, %lu bytes) failed",
723 sdr->sockfd, (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
724 goto cleanup;
725 }
726 #endif
727
728 if (!MakeSeparateReturnSocket)
729 errsd = sdr->sockfd;
730 if (MakeSeparateReturnSocket || sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf
731 {
732 #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
733 // At this point we may wait in accept for a few milliseconds waiting for the daemon to connect back to us,
734 // but that's okay -- the daemon should not take more than a few milliseconds to respond.
735 // set_waitlimit() ensures we do not block indefinitely just in case something is wrong
736 dnssd_sockaddr_t daddr;
737 dnssd_socklen_t len = sizeof(daddr);
738 if ((err = set_waitlimit(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError)
739 goto cleanup;
740 errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
741 if (!dnssd_SocketValid(errsd))
742 deliver_request_bailout("accept");
743 #else
744
745 struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS
746 struct msghdr msg;
747 struct cmsghdr *cmsg;
748 char cbuf[CMSG_SPACE(4 * sizeof(dnssd_sock_t))];
749
750 msg.msg_name = 0;
751 msg.msg_namelen = 0;
752 msg.msg_iov = &vec;
753 msg.msg_iovlen = 1;
754 msg.msg_flags = 0;
755 if (MakeSeparateReturnSocket || sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf
756 {
757 if (sdr->op == send_bpf)
758 {
759 int i;
760 char p[12]; // Room for "/dev/bpf999" with terminating null
761 for (i=0; i<100; i++)
762 {
|
577 syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect()-> No of tries: %d", NumTries);
578 sleep(1); // Sleep a bit, then try again
579 }
580 else
581 {
582 syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect() failed path:%s Socket:%d Err:%d Errno:%d %s",
583 uds_serverpath, sdr->sockfd, err, dnssd_errno, dnssd_strerror(dnssd_errno));
584 dnssd_close(sdr->sockfd);
585 FreeDNSServiceOp(sdr);
586 return kDNSServiceErr_ServiceNotRunning;
587 }
588 }
589 //printf("ConnectToServer opened socket %d\n", sdr->sockfd);
590 }
591
592 *ref = sdr;
593 return kDNSServiceErr_NoError;
594 }
595
596 #define deliver_request_bailout(MSG) \
597 syslog(LOG_WARNING, "dnssd_clientstub deliver_request: %s failed %d (%s)", (MSG), dnssd_errno, dnssd_strerror(dnssd_errno)); goto cleanup
598
599 static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
600 {
601 uint32_t datalen = hdr->datalen; // We take a copy here because we're going to convert hdr->datalen to network byte order
602 #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
603 char *const data = (char *)hdr + sizeof(ipc_msg_hdr);
604 #endif
605 dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
606 DNSServiceErrorType err = kDNSServiceErr_Unknown; // Default for the "goto cleanup" cases
607 int MakeSeparateReturnSocket = 0;
608
609 // Note: need to check hdr->op, not sdr->op.
610 // hdr->op contains the code for the specific operation we're currently doing, whereas sdr->op
611 // contains the original parent DNSServiceOp (e.g. for an add_record_request, hdr->op will be
612 // add_record_request but the parent sdr->op will be connection_request or reg_service_request)
613 if (sdr->primary ||
614 hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request)
615 MakeSeparateReturnSocket = 1;
616
617 if (!DNSServiceRefValid(sdr))
619 if (hdr)
620 free(hdr);
621 syslog(LOG_WARNING, "dnssd_clientstub deliver_request: invalid DNSServiceRef %p %08X %08X", sdr, sdr->sockfd, sdr->validator);
622 return kDNSServiceErr_BadReference;
623 }
624
625 if (!hdr)
626 {
627 syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr");
628 return kDNSServiceErr_Unknown;
629 }
630
631 if (MakeSeparateReturnSocket)
632 {
633 #if defined(USE_TCP_LOOPBACK)
634 {
635 union { uint16_t s; u_char b[2]; } port;
636 dnssd_sockaddr_t caddr;
637 dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
638 listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
639 if (!dnssd_SocketValid(listenfd)) {
640 deliver_request_bailout("TCP socket");
641 }
642
643 caddr.sin_family = AF_INET;
644 caddr.sin_port = 0;
645 caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
646 if (bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)) < 0) {
647 deliver_request_bailout("TCP bind");
648 }
649 if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) {
650 deliver_request_bailout("TCP getsockname");
651 }
652 if (listen(listenfd, 1) < 0) {
653 deliver_request_bailout("TCP listen");
654 }
655 port.s = caddr.sin_port;
656 data[0] = port.b[0]; // don't switch the byte order, as the
657 data[1] = port.b[1]; // daemon expects it in network byte order
658 }
659 #elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
660 {
661 mode_t mask;
662 int bindresult;
663 dnssd_sockaddr_t caddr;
664 listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
665 if (!dnssd_SocketValid(listenfd)) {
666 deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket");
667 }
668
669 caddr.sun_family = AF_LOCAL;
670 // According to Stevens (section 3.2), there is no portable way to
671 // determine whether sa_len is defined on a particular platform.
672 #ifndef NOT_HAVE_SA_LEN
673 caddr.sun_len = sizeof(struct sockaddr_un);
674 #endif
675 strcpy(caddr.sun_path, data);
676 mask = umask(0);
677 bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
678 umask(mask);
679 if (bindresult < 0) {
680 deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET bind");
681 }
682 if (listen(listenfd, 1) < 0) {
683 deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen");
684 }
685 }
686 #else
687 {
688 dnssd_sock_t sp[2];
689 if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) {
690 deliver_request_bailout("socketpair");
691 }
692 else
693 {
694 errsd = sp[0]; // We'll read our four-byte error code from sp[0]
695 listenfd = sp[1]; // We'll send sp[1] to the daemon
696 #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
697 {
698 int defunct = 1;
699 if (setsockopt(errsd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
700 syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
701 }
702 #endif
703 }
704 }
705 #endif
706 }
707
708 #if !defined(USE_TCP_LOOPBACK) && !defined(USE_NAMED_ERROR_RETURN_SOCKET)
709 // If we're going to make a separate error return socket, and pass it to the daemon
710 // using sendmsg, then we'll hold back one data byte to go with it.
711 // On some versions of Unix (including Leopard) sending a control message without
737 // in the case of DEFUNCT sockets
738 syslog(LOG_INFO, "dnssd_clientstub deliver_request ERROR: write_all(%d, %lu bytes) failed",
739 sdr->sockfd, (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
740 goto cleanup;
741 }
742 #endif
743
744 if (!MakeSeparateReturnSocket)
745 errsd = sdr->sockfd;
746 if (MakeSeparateReturnSocket || sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf
747 {
748 #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
749 // At this point we may wait in accept for a few milliseconds waiting for the daemon to connect back to us,
750 // but that's okay -- the daemon should not take more than a few milliseconds to respond.
751 // set_waitlimit() ensures we do not block indefinitely just in case something is wrong
752 dnssd_sockaddr_t daddr;
753 dnssd_socklen_t len = sizeof(daddr);
754 if ((err = set_waitlimit(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError)
755 goto cleanup;
756 errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
757 if (!dnssd_SocketValid(errsd)) {
758 deliver_request_bailout("accept");
759 }
760 #else
761
762 struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS
763 struct msghdr msg;
764 struct cmsghdr *cmsg;
765 char cbuf[CMSG_SPACE(4 * sizeof(dnssd_sock_t))];
766
767 msg.msg_name = 0;
768 msg.msg_namelen = 0;
769 msg.msg_iov = &vec;
770 msg.msg_iovlen = 1;
771 msg.msg_flags = 0;
772 if (MakeSeparateReturnSocket || sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf
773 {
774 if (sdr->op == send_bpf)
775 {
776 int i;
777 char p[12]; // Room for "/dev/bpf999" with terminating null
778 for (i=0; i<100; i++)
779 {
|