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
+ the Free Software Foundation; either version 3 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.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
+#include "nmbd/nmbd.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;
- nstring qname;
+ unstring qname;
+
+ pull_ascii_nstring(qname, sizeof(qname), question->name);
- pull_ascii_nstring(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));
- (void)add_name_to_subnet( wins_server_subnet, qname, name_type,
+ add_name_to_subnet( wins_server_subnet, qname, name_type,
NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr );
- return( NULL );
+ 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)));
- return( add_name_to_subnet( wins_server_subnet, qname, name_type,
- NB_ACTIVE, 2*60*60, DNS_NAME, 1, &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_DNS
static void asyncdns_process(void)
{
struct query_record r;
- fstring qname;
+ unstring qname;
DEBUGLEVEL = -1;
while (1) {
- if (read_data(fd_in, (char *)&r, sizeof(r)) != sizeof(r))
- break;
+ NTSTATUS status;
- fstrcpy(qname, r.name.name);
+ status = read_data(fd_in, (char *)&r, sizeof(r));
+ if (!NT_STATUS_IS_OK(status)) {
+ 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))
/***************************************************************************
create a child process to handle DNS lookups
****************************************************************************/
-void start_async_dns(void)
+void start_async_dns(struct messaging_context *msg)
{
int fd1[2], fd2[2];
+ NTSTATUS status;
CatchChild();
return;
}
- child_pid = sys_fork();
+ child_pid = fork();
if (child_pid) {
fd_in = fd1[0];
CatchSignal(SIGUSR2, SIG_IGN);
CatchSignal(SIGUSR1, SIG_IGN);
CatchSignal(SIGHUP, SIG_IGN);
- CatchSignal(SIGTERM, SIGNAL_CAST sig_term );
+ CatchSignal(SIGTERM, sig_term);
+
+ status = reinit_after_fork(msg, nmbd_event_context(), true);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("reinit_after_fork() failed\n"));
+ smb_panic("reinit_after_fork() failed");
+ }
asyncdns_process();
}
/***************************************************************************
check if a particular name is already being queried
****************************************************************************/
-static BOOL query_current(struct query_record *r)
+static bool query_current(struct query_record *r)
{
return dns_current &&
nmb_name_equal(&r->name,
/***************************************************************************
write a query to the child process
****************************************************************************/
-static BOOL write_child(struct packet_struct *p)
+static bool write_child(struct packet_struct *p)
{
struct query_record r;
/***************************************************************************
check the DNS queue
****************************************************************************/
-void run_dns_queue(void)
+void run_dns_queue(struct messaging_context *msg)
{
struct query_record r;
struct packet_struct *p, *p2;
struct name_record *namerec;
- int size;
+ NTSTATUS status;
if (fd_in == -1)
return;
- /* Allow SIGTERM to kill us. */
- BlockSignals(False, SIGTERM);
-
- if (!process_exists(child_pid)) {
+ if (!process_exists_by_pid(child_pid)) {
close(fd_in);
- start_async_dns();
+ close(fd_out);
+ start_async_dns(msg);
}
- 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);
+ status = read_data(fd_in, (char *)&r, sizeof(r));
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("read from child failed: %s\n", nt_errstr(status)));
+ fd_in = -1;
return;
}
- BlockSignals(True, SIGTERM);
-
namerec = add_dns_result(&r.name, r.result);
if (dns_current) {
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;
+ DLIST_REMOVE(dns_queue, p);
free_packet(p);
p = p2;
} else {
if (dns_queue) {
dns_current = dns_queue;
- dns_queue = dns_queue->next;
- if (dns_queue)
- dns_queue->prev = NULL;
- dns_current->next = NULL;
+ DLIST_REMOVE(dns_queue, dns_queue);
if (!write_child(dns_current)) {
DEBUG(3,("failed to send DNS query to child!\n"));
queue a DNS query
****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n)
+bool queue_dns_query(struct packet_struct *p,struct nmb_name *question)
{
if (in_dns || fd_in == -1)
return False;
p->locked = True;
} else {
p->locked = True;
- p->next = dns_queue;
- p->prev = NULL;
- if (p->next)
- p->next->prev = p;
- dns_queue = p;
+ DLIST_ADD(dns_queue, p);
}
DEBUG(3,("added DNS query for %s\n", nmb_namestr(question)));
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)
+bool queue_dns_query(struct packet_struct *p,struct nmb_name *question)
{
+ struct name_record *namerec = NULL;
struct in_addr dns_ip;
- nstring qname;
+ unstring qname;
- pull_ascii_nstring(qname, question->name);
+ pull_ascii_nstring(qname, sizeof(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);
-
- *n = add_dns_result(question, dns_ip);
- if(*n == NULL)
+ 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, *n);
+ } else {
+ send_wins_name_query_response(0, p, namerec);
+ }
return False;
}