2 Unix SMB/Netbios implementation.
4 Copyright (C) Andrew Tridgell 1997
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 extern int DEBUGLEVEL;
26 /***************************************************************************
27 add a DNS result to the name cache
28 ****************************************************************************/
29 static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr addr)
31 int name_type = question->name_type;
32 char *qname = question->name;
35 /* add the fail to WINS cache of names. give it 1 hour in the cache */
36 DEBUG(3,("Negative DNS answer for %s\n", qname));
37 add_netbios_entry(wins_client_subnet,qname,name_type,NB_ACTIVE,60*60,
42 /* add it to our WINS cache of names. give it 2 hours in the cache */
43 DEBUG(3,("DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));
45 return add_netbios_entry(wins_client_subnet,qname,name_type,NB_ACTIVE,
46 2*60*60,DNS,addr, True);
53 static int fd_in = -1, fd_out = -1;
54 static int child_pid = -1;
57 /* this is the structure that is passed between the parent and child */
60 struct in_addr result;
63 /* a queue of pending requests waiting to be sent to the DNS child */
64 static struct packet_struct *dns_queue;
66 /* the packet currently being processed by the dns child */
67 static struct packet_struct *dns_current;
70 /***************************************************************************
71 return the fd used to gather async dns replies. This is added to the select
73 ****************************************************************************/
79 /***************************************************************************
80 handle DNS queries arriving from the parent
81 ****************************************************************************/
82 static void asyncdns_process(void)
84 struct query_record r;
90 if (read_data(fd_in, (char *)&r, sizeof(r)) != sizeof(r))
93 fstrcpy(qname, r.name.name);
95 r.result.s_addr = interpret_addr(qname);
97 if (write_data(fd_out, (char *)&r, sizeof(r)) != sizeof(r))
105 /***************************************************************************
106 create a child process to handle DNS lookups
107 ****************************************************************************/
108 void start_async_dns(void)
112 signal(SIGCLD, SIG_IGN);
114 if (pipe(fd1) || pipe(fd2)) {
131 signal(SIGUSR2, SIG_IGN);
132 signal(SIGUSR1, SIG_IGN);
133 signal(SIGHUP, SIG_IGN);
139 /***************************************************************************
140 check if a particular name is already being queried
141 ****************************************************************************/
142 static BOOL query_current(struct query_record *r)
144 return dns_current &&
146 &dns_current->packet.nmb.question.question_name);
150 /***************************************************************************
151 write a query to the child process
152 ****************************************************************************/
153 static BOOL write_child(struct packet_struct *p)
155 struct query_record r;
157 r.name = p->packet.nmb.question.question_name;
159 return write_data(fd_out, (char *)&r, sizeof(r)) == sizeof(r);
162 /***************************************************************************
164 ****************************************************************************/
165 void run_dns_queue(void)
167 struct query_record r;
168 struct packet_struct *p, *p2;
174 if (!process_exists(child_pid)) {
179 if ((size=read_data(fd_in, (char *)&r, sizeof(r))) != sizeof(r)) {
181 DEBUG(0,("Incomplete DNS answer from child!\n"));
187 add_dns_result(&r.name, r.result);
190 if (query_current(&r)) {
191 DEBUG(3,("DNS calling reply_name_query\n"));
193 reply_name_query(dns_current);
197 dns_current->locked = False;
198 free_packet(dns_current);
202 /* loop over the whole dns queue looking for entries that
203 match the result we just got */
204 for (p = dns_queue; p;) {
205 struct nmb_packet *nmb = &p->packet.nmb;
206 struct nmb_name *question = &nmb->question.question_name;
208 if (name_equal(question, &r.name)) {
209 DEBUG(3,("DNS calling reply_name_query\n"));
216 p->prev->next = p->next;
220 p->next->prev = p->prev;
230 dns_current = dns_queue;
231 dns_queue = dns_queue->next;
232 if (dns_queue) dns_queue->prev = NULL;
233 dns_current->next = NULL;
235 if (!write_child(dns_current)) {
236 DEBUG(3,("failed to send DNS query to child!\n"));
243 /***************************************************************************
245 ****************************************************************************/
246 BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
247 struct name_record **n)
249 if (in_dns || fd_in == -1)
253 if (!write_child(p)) {
254 DEBUG(3,("failed to send DNS query to child!\n"));
268 DEBUG(3,("added DNS query for %s\n", namestr(question)));
275 /***************************************************************************
276 we use this then we can't do async DNS lookups
277 ****************************************************************************/
278 BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
279 struct name_record **n)
281 char *qname = question->name;
282 struct in_addr dns_ip;
284 DEBUG(3,("DNS search for %s - ", namestr(question)));
286 dns_ip.s_addr = interpret_addr(qname);
288 *n = add_dns_result(question, dns_ip);