⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asyncdns.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
字号:
/*   Unix SMB/CIFS implementation.   a async DNS handler   Copyright (C) Andrew Tridgell 1997-1998      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */#include "includes.h"/***************************************************************************  Add a DNS result to the name cache.****************************************************************************/static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr addr){	int name_type = question->name_type;	unstring qname;	pull_ascii_nstring(qname, sizeof(qname), question->name);  	if (!addr.s_addr) {		/* add the fail to WINS cache of names. give it 1 hour in the cache */		DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname));		add_name_to_subnet( wins_server_subnet, qname, name_type,				NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr );		return NULL;	}	/* add it to our WINS cache of names. give it 2 hours in the cache */	DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));	add_name_to_subnet( wins_server_subnet, qname, name_type,                              NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr);	return find_name_on_subnet(wins_server_subnet, question, FIND_ANY_NAME);}#ifndef SYNC_DNSstatic int fd_in = -1, fd_out = -1;static pid_t child_pid = -1;static int in_dns;/* this is the structure that is passed between the parent and child */struct query_record {	struct nmb_name name;	struct in_addr result;};/* a queue of pending requests waiting to be sent to the DNS child */static struct packet_struct *dns_queue;/* the packet currently being processed by the dns child */static struct packet_struct *dns_current;/***************************************************************************  return the fd used to gather async dns replies. This is added to the select  loop  ****************************************************************************/int asyncdns_fd(void){	return fd_in;}/***************************************************************************  handle DNS queries arriving from the parent  ****************************************************************************/static void asyncdns_process(void){	struct query_record r;	unstring qname;	DEBUGLEVEL = -1;	while (1) {		if (read_data(fd_in, (char *)&r, sizeof(r)) != sizeof(r)) 			break;		pull_ascii_nstring( qname, sizeof(qname), r.name.name);		r.result.s_addr = interpret_addr(qname);		if (write_data(fd_out, (char *)&r, sizeof(r)) != sizeof(r))			break;	}	_exit(0);}/**************************************************************************** **  catch a sigterm (in the child process - the parent has a different handler  see nmbd.c for details).  We need a separate term handler here so we don't release any   names that our parent is going to release, or overwrite a   WINS db that our parent is going to write. **************************************************************************** */static void sig_term(int sig){	_exit(0);}/*************************************************************************** Called by the parent process when it receives a SIGTERM - also kills the child so we don't get child async dns processes lying around, causing trouble.  ****************************************************************************/void kill_async_dns_child(void){	if (child_pid > 0) {		kill(child_pid, SIGTERM);		child_pid = -1;	}}/***************************************************************************  create a child process to handle DNS lookups  ****************************************************************************/void start_async_dns(void){	int fd1[2], fd2[2];	CatchChild();	if (pipe(fd1) || pipe(fd2)) {		DEBUG(0,("can't create asyncdns pipes\n"));		return;	}	child_pid = sys_fork();	if (child_pid) {		fd_in = fd1[0];		fd_out = fd2[1];		close(fd1[1]);		close(fd2[0]);		DEBUG(0,("started asyncdns process %d\n", (int)child_pid));		return;	}	fd_in = fd2[0];	fd_out = fd1[1];	CatchSignal(SIGUSR2, SIG_IGN);	CatchSignal(SIGUSR1, SIG_IGN);	CatchSignal(SIGHUP, SIG_IGN);        CatchSignal(SIGTERM, SIGNAL_CAST sig_term );	asyncdns_process();}/***************************************************************************check if a particular name is already being queried  ****************************************************************************/static BOOL query_current(struct query_record *r){	return dns_current &&		nmb_name_equal(&r->name, 			   &dns_current->packet.nmb.question.question_name);}/***************************************************************************  write a query to the child process  ****************************************************************************/static BOOL write_child(struct packet_struct *p){	struct query_record r;	r.name = p->packet.nmb.question.question_name;	return write_data(fd_out, (char *)&r, sizeof(r)) == sizeof(r);}/***************************************************************************  check the DNS queue  ****************************************************************************/void run_dns_queue(void){	struct query_record r;	struct packet_struct *p, *p2;	struct name_record *namerec;	int size;	if (fd_in == -1)		return;        /* Allow SIGTERM to kill us. */        BlockSignals(False, SIGTERM);	if (!process_exists_by_pid(child_pid)) {		close(fd_in);		start_async_dns();	}	if ((size=read_data(fd_in, (char *)&r, sizeof(r))) != sizeof(r)) {		if (size) {			DEBUG(0,("Incomplete DNS answer from child!\n"));			fd_in = -1;		}                BlockSignals(True, SIGTERM);		return;	}        BlockSignals(True, SIGTERM);	namerec = add_dns_result(&r.name, r.result);	if (dns_current) {		if (query_current(&r)) {			DEBUG(3,("DNS calling send_wins_name_query_response\n"));			in_dns = 1;			if(namerec == NULL)				send_wins_name_query_response(NAM_ERR, dns_current, NULL);			else				send_wins_name_query_response(0,dns_current,namerec);			in_dns = 0;		}		dns_current->locked = False;		free_packet(dns_current);		dns_current = NULL;	}	/* loop over the whole dns queue looking for entries that	   match the result we just got */	for (p = dns_queue; p;) {		struct nmb_packet *nmb = &p->packet.nmb;		struct nmb_name *question = &nmb->question.question_name;		if (nmb_name_equal(question, &r.name)) {			DEBUG(3,("DNS calling send_wins_name_query_response\n"));			in_dns = 1;			if(namerec == NULL)				send_wins_name_query_response(NAM_ERR, p, NULL);			else				send_wins_name_query_response(0,p,namerec);			in_dns = 0;			p->locked = False;			if (p->prev)				p->prev->next = p->next;			else				dns_queue = p->next;			if (p->next)				p->next->prev = p->prev;			p2 = p->next;			free_packet(p);			p = p2;		} else {			p = p->next;		}	}	if (dns_queue) {		dns_current = dns_queue;		dns_queue = dns_queue->next;		if (dns_queue)			dns_queue->prev = NULL;		dns_current->next = NULL;		if (!write_child(dns_current)) {			DEBUG(3,("failed to send DNS query to child!\n"));			return;		}	}}/***************************************************************************queue a DNS query  ****************************************************************************/BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,		     struct name_record **n){	if (in_dns || fd_in == -1)		return False;	if (!dns_current) {		if (!write_child(p)) {			DEBUG(3,("failed to send DNS query to child!\n"));			return False;		}		dns_current = p;		p->locked = True;	} else {		p->locked = True;		p->next = dns_queue;		p->prev = NULL;		if (p->next)			p->next->prev = p;		dns_queue = p;	}	DEBUG(3,("added DNS query for %s\n", nmb_namestr(question)));	return True;}#else/***************************************************************************  we use this when we can't do async DNS lookups  ****************************************************************************/BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,		     struct name_record **n){	struct name_record *namerec = NULL;	struct in_addr dns_ip;	unstring qname;	pull_ascii_nstring(qname, question->name);	DEBUG(3,("DNS search for %s - ", nmb_namestr(question)));        /* Unblock TERM signal so we can be killed in DNS lookup. */        BlockSignals(False, SIGTERM);	dns_ip.s_addr = interpret_addr(qname);        /* Re-block TERM signal. */        BlockSignals(True, SIGTERM);	namerec = add_dns_result(question, dns_ip);	if(namerec == NULL) {		send_wins_name_query_response(NAM_ERR, p, NULL);	} else {		send_wins_name_query_response(0, p, namerec);	}	return False;}/*************************************************************************** With sync dns there is no child to kill on SIGTERM.  ****************************************************************************/void kill_async_dns_child(void){	return;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -