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