Print this page
6771 end-of-loop code not reached in common/dnssd_clientstub.c


 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                 {