Mercurial > dnsbl
comparison src/dnsbl.cpp @ 61:7f44a4974bf6 stable-4-2
Use resolver processes even if we don't have the interfaces, and need to use gethostbyname.
author | carl |
---|---|
date | Sat, 08 Jan 2005 12:26:30 -0800 |
parents | 390ed250c5d2 |
children | 7ad7d8b100bf |
comparison
equal
deleted
inserted
replaced
60:390ed250c5d2 | 61:7f44a4974bf6 |
---|---|
204 static char *resolver_port = NULL; // unix domain socket to talk to the dns resolver process | 204 static char *resolver_port = NULL; // unix domain socket to talk to the dns resolver process |
205 static int resolver_socket = NULL_SOCKET; // socket used to listen for resolver requests | 205 static int resolver_socket = NULL_SOCKET; // socket used to listen for resolver requests |
206 static time_t ERROR_SOCKET_TIME = 60; // number of seconds between attempts to open the spam filter socket | 206 static time_t ERROR_SOCKET_TIME = 60; // number of seconds between attempts to open the spam filter socket |
207 static time_t last_error_time; | 207 static time_t last_error_time; |
208 | 208 |
209 #ifdef NS_PACKETSZ | 209 |
210 // packed structure to allow a single socket write to dump the | 210 // packed structure to allow a single socket write to dump the |
211 // length and the following answer. The packing attribute is gcc specific. | 211 // length and the following answer. The packing attribute is gcc specific. |
212 struct glommer { | 212 struct glommer { |
213 int length; | 213 int length; |
214 u_char answer[NS_PACKETSZ]; | 214 #ifdef NS_PACKETSZ |
215 } __attribute__ ((packed)); | 215 u_char answer[NS_PACKETSZ]; // with a resolver, we return resolver answers |
216 #endif | 216 #else |
217 int answer; // without a resolver, we return a single ip4 address, 0 == no answer | |
218 #endif | |
219 } __attribute__ ((packed)); | |
217 | 220 |
218 struct mlfiPriv; | 221 struct mlfiPriv; |
219 | 222 |
220 | 223 |
221 //////////////////////////////////////////////// | 224 //////////////////////////////////////////////// |
607 | 610 |
608 //////////////////////////////////////////////// | 611 //////////////////////////////////////////////// |
609 // read a resolver request from the socket, process it, and | 612 // read a resolver request from the socket, process it, and |
610 // write the result back to the socket. | 613 // write the result back to the socket. |
611 | 614 |
612 #ifdef NS_PACKETSZ | |
613 static void process_resolver_requests(int socket); | 615 static void process_resolver_requests(int socket); |
614 static void process_resolver_requests(int socket) { | 616 static void process_resolver_requests(int socket) { |
615 #ifdef NS_MAXDNAME | 617 #ifdef NS_MAXDNAME |
616 char question[NS_MAXDNAME]; | 618 char question[NS_MAXDNAME]; |
617 #else | 619 #else |
640 return; | 642 return; |
641 } | 643 } |
642 } | 644 } |
643 | 645 |
644 // find the answer | 646 // find the answer |
647 #ifdef NS_PACKETSZ | |
645 //char text[1000]; | 648 //char text[1000]; |
646 //snprintf(text, sizeof(text), "!!child worker process has a question %s", question); | 649 //snprintf(text, sizeof(text), "!!child worker process has a question %s", question); |
647 //my_syslog(text); | 650 //my_syslog(text); |
648 glom.length = res_search(question, ns_c_in, ns_t_a, glom.answer, sizeof(glom.answer)); | 651 glom.length = res_search(question, ns_c_in, ns_t_a, glom.answer, sizeof(glom.answer)); |
649 if (glom.length < 0) glom.length = 0; // represent all errors as zero length answers | 652 if (glom.length < 0) glom.length = 0; // represent all errors as zero length answers |
653 #else | |
654 glom.length = sizeof(glom.answer); | |
655 glom.answer = 0; | |
656 struct hostent *host = gethostbyname(question); | |
657 if (host && (host->h_addrtype == AF_INET)) { | |
658 memcpy(&glom.answer, host->h_addr, sizeof(glom.answer)); | |
659 } | |
660 #endif | |
650 | 661 |
651 // write the answer | 662 // write the answer |
652 char *buf = (char *)&glom; | 663 char *buf = (char *)&glom; |
653 int len = glom.length + sizeof(glom.length); | 664 int len = glom.length + sizeof(glom.length); |
654 //snprintf(text, sizeof(text), "!!child worker process writing answer length %d for total %d", glom.length, len); | 665 //snprintf(text, sizeof(text), "!!child worker process writing answer length %d for total %d", glom.length, len); |
667 return; | 678 return; |
668 } | 679 } |
669 } | 680 } |
670 } | 681 } |
671 } | 682 } |
672 #endif | |
673 | 683 |
674 | 684 |
675 //////////////////////////////////////////////// | 685 //////////////////////////////////////////////// |
676 // ask a dns question and get an A record answer - we don't try | 686 // ask a dns question and get an A record answer - we don't try |
677 // very hard, just using the default resolver retry settings. | 687 // very hard, just using the default resolver retry settings. |
678 // If we cannot get an answer, we just accept the mail. | 688 // If we cannot get an answer, we just accept the mail. |
679 // | 689 // |
680 // | 690 // |
681 static int dns_interface(mlfiPriv &priv, char *question, bool maybe_ip, ns_map *nameservers); | 691 static int dns_interface(mlfiPriv &priv, char *question, bool maybe_ip, ns_map *nameservers); |
682 static int dns_interface(mlfiPriv &priv, char *question, bool maybe_ip, ns_map *nameservers) { | 692 static int dns_interface(mlfiPriv &priv, char *question, bool maybe_ip, ns_map *nameservers) { |
683 int ret_address = 0; | |
684 #ifdef NS_PACKETSZ | |
685 | |
686 // this part can be done without locking the resolver mutex. Each | 693 // this part can be done without locking the resolver mutex. Each |
687 // milter thread is talking over its own socket to a separate resolver | 694 // milter thread is talking over its own socket to a separate resolver |
688 // process, which does the actual dns resolution. | 695 // process, which does the actual dns resolution. |
689 if (priv.err) return 0; // cannot ask more questions on this socket. | 696 if (priv.err) return 0; // cannot ask more questions on this socket. |
690 priv.my_write(question, strlen(question)+1); // write the question including the null terminator | 697 priv.my_write(question, strlen(question)+1); // write the question including the null terminator |
699 priv.err = true; | 706 priv.err = true; |
700 return 0; // cannot process overlarge answers | 707 return 0; // cannot process overlarge answers |
701 } | 708 } |
702 priv.my_read(buf, glom.length); | 709 priv.my_read(buf, glom.length); |
703 | 710 |
711 #ifdef NS_PACKETSZ | |
704 // now we need to lock the resolver mutex to keep the milter threads from | 712 // now we need to lock the resolver mutex to keep the milter threads from |
705 // stepping on each other while parsing the dns answer. | 713 // stepping on each other while parsing the dns answer. |
714 int ret_address = 0; | |
706 pthread_mutex_lock(&resolve_mutex); | 715 pthread_mutex_lock(&resolve_mutex); |
707 if (glom.length > 0) { | 716 if (glom.length > 0) { |
708 // parse the answer | 717 // parse the answer |
709 ns_msg handle; | 718 ns_msg handle; |
710 ns_rr rr; | 719 ns_rr rr; |
772 ret_address = ip.s_addr; | 781 ret_address = ip.s_addr; |
773 } | 782 } |
774 } | 783 } |
775 pthread_mutex_unlock(&resolve_mutex); | 784 pthread_mutex_unlock(&resolve_mutex); |
776 return ret_address; | 785 return ret_address; |
777 | |
778 #else | 786 #else |
779 // systems without the resolver interface | 787 return glom.answer; |
780 pthread_mutex_lock(&resolve_mutex); | |
781 struct hostent *host = gethostbyname(question); | |
782 if (host && (host->h_addrtype == AF_INET)) { | |
783 memcpy(&ret_address, host->h_addr, sizeof(ret_address)); | |
784 } | |
785 pthread_mutex_unlock(&resolve_mutex); | |
786 return ret_address; | |
787 #endif | 788 #endif |
788 } | 789 } |
789 | 790 |
790 | 791 |
791 //////////////////////////////////////////////// | 792 //////////////////////////////////////////////// |
1757 if (setuid(pw->pw_uid) == -1) { | 1758 if (setuid(pw->pw_uid) == -1) { |
1758 my_syslog("failed to switch to user dnsbl"); | 1759 my_syslog("failed to switch to user dnsbl"); |
1759 } | 1760 } |
1760 } | 1761 } |
1761 | 1762 |
1762 #ifdef NS_PACKETSZ | |
1763 // fork off the resolver listener process | 1763 // fork off the resolver listener process |
1764 pid_t child = fork(); | 1764 pid_t child = fork(); |
1765 if (child < 0) { | 1765 if (child < 0) { |
1766 my_syslog("failed to create resolver listener process"); | 1766 my_syslog("failed to create resolver listener process"); |
1767 exit(0); | 1767 exit(0); |
1815 int newchild = fork(); | 1815 int newchild = fork(); |
1816 if (newchild == 0) { | 1816 if (newchild == 0) { |
1817 // this is the worker process | 1817 // this is the worker process |
1818 // child does not need the listening socket | 1818 // child does not need the listening socket |
1819 close(resolver_socket); | 1819 close(resolver_socket); |
1820 my_syslog("child forked a worker process"); | 1820 //my_syslog("child forked a worker process"); |
1821 process_resolver_requests(s); | 1821 process_resolver_requests(s); |
1822 my_syslog("child terminated a worker process"); | 1822 //my_syslog("child terminated a worker process"); |
1823 exit(0); | 1823 exit(0); |
1824 } | 1824 } |
1825 else { | 1825 else { |
1826 // this is the parent | 1826 // this is the parent |
1827 // parent does not need the accepted socket | 1827 // parent does not need the accepted socket |
1832 exit(0); // make sure we don't fall thru. | 1832 exit(0); // make sure we don't fall thru. |
1833 } | 1833 } |
1834 else { | 1834 else { |
1835 sleep(2); // allow child to get started | 1835 sleep(2); // allow child to get started |
1836 } | 1836 } |
1837 #endif | |
1838 | 1837 |
1839 // load the initial config | 1838 // load the initial config |
1840 config = new_conf(); | 1839 config = new_conf(); |
1841 | 1840 |
1842 // only create threads after the fork() in daemon | 1841 // only create threads after the fork() in daemon |