2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
6 Copyright (C) Jeremy Allison 1994-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /****************************************************************************
27 Deal with a response packet when querying a name.
28 ****************************************************************************/
30 static void query_name_response( struct subnet_record *subrec,
31 struct response_record *rrec,
32 struct packet_struct *p)
34 struct nmb_packet *nmb = &p->packet.nmb;
36 struct nmb_name *question_name =
37 &rrec->packet->packet.nmb.question.question_name;
38 struct in_addr answer_ip;
42 /* Ensure we don't retry the query but leave the response record cleanup
43 to the timeout code. We may get more answer responses in which case
44 we should mark the name in conflict.. */
45 rrec->repeat_count = 0;
47 if(rrec->num_msgs == 1)
49 /* This is the first response. */
51 if(nmb->header.opcode == NMB_WACK_OPCODE)
53 /* WINS server is telling us to wait. Pretend we didn't get
54 the response but don't send out any more query requests. */
58 dbgtext( "query_name_response: " );
59 dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) );
60 dbgtext( "in querying name %s ", nmb_namestr(question_name) );
61 dbgtext( "on subnet %s.\n", subrec->subnet_name );
64 rrec->repeat_count = 0;
65 /* How long we should wait for. */
66 rrec->repeat_time = p->timestamp + nmb->answers->ttl;
70 else if(nmb->header.rcode != 0)
76 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
77 dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) );
78 dbgtext( "for name %s. ", nmb_namestr(question_name) );
79 dbgtext( "Error code was %d.\n", nmb->header.rcode );
86 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
87 dbgtext( "IP %s ", inet_ntoa(p->ip) );
88 dbgtext( "returned a success response with no answer\n" );
94 putip((char *)&answer_ip,&nmb->answers->rdata[2]);
97 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
98 dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) );
99 dbgtext( "for name %s. ", nmb_namestr(question_name) );
100 dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) );
103 /* Interestingly, we could add these names to our namelists, and
104 change nmbd to a model that checked its own name cache first,
105 before sending out a query. This is a task for another day, though.
109 else if( rrec->num_msgs > 1)
114 putip( (char *)&answer_ip, &nmb->answers->rdata[2] );
115 dbgtext( "query_name_response: " );
116 dbgtext( "Multiple (%d) responses ", rrec->num_msgs );
117 dbgtext( "received for a query on subnet %s ", subrec->subnet_name );
118 dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) );
119 dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) );
120 dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) );
123 /* We have already called the success or fail function, so we
124 don't call again here. Leave the response record around in
125 case we get more responses. */
130 if(success && rrec->success_fn)
131 (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers);
132 else if( rrec->fail_fn)
133 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode);
137 /****************************************************************************
138 Deal with a timeout when querying a name.
139 ****************************************************************************/
141 static void query_name_timeout_response(struct subnet_record *subrec,
142 struct response_record *rrec)
144 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
145 /* We can only fail here, never succeed. */
147 struct nmb_name *question_name = &sent_nmb->question.question_name;
149 if(rrec->num_msgs != 0)
151 /* We got at least one response, and have called the success/fail
161 dbgtext( "query_name_timeout_response: No response to " );
162 dbgtext( "query for name %s ", nmb_namestr(question_name) );
163 dbgtext( "on subnet %s.\n", subrec->subnet_name );
166 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0);
169 remove_response_record(subrec, rrec);
172 /****************************************************************************
173 Lookup a name on our local namelists. We check the lmhosts file first. If the
174 name is not there we look for the name on the given subnet.
175 ****************************************************************************/
177 static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname,
178 struct name_record **namerecp)
180 struct name_record *namerec;
184 if(find_name_in_lmhosts(nmbname, namerecp))
187 if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL)
190 if( NAME_IS_ACTIVE(namerec)
191 && ( (namerec->data.source == SELF_NAME)
192 || (namerec->data.source == LMHOSTS_NAME) ) )
200 /****************************************************************************
201 Try and query for a name.
202 ****************************************************************************/
204 BOOL query_name(struct subnet_record *subrec, const char *name, int type,
205 query_name_success_function success_fn,
206 query_name_fail_function fail_fn,
207 struct userdata_struct *userdata)
209 struct nmb_name nmbname;
210 struct name_record *namerec;
212 make_nmb_name(&nmbname, name, type);
215 * We need to check our local namelists first.
216 * It may be an magic name, lmhosts name or just
217 * a name we have registered.
220 if(query_local_namelists(subrec, &nmbname, &namerec) == True)
225 memset((char *)&rrec, '\0', sizeof(struct res_rec));
227 /* Fake up the needed res_rec just in case it's used. */
228 rrec.rr_name = nmbname;
229 rrec.rr_type = RR_TYPE_NB;
230 rrec.rr_class = RR_CLASS_IN;
231 rrec.ttl = PERMANENT_TTL;
232 rrec.rdlength = namerec->data.num_ips * 6;
233 if(rrec.rdlength > MAX_DGRAM_SIZE)
237 dbgtext( "query_name: nmbd internal error - " );
238 dbgtext( "there are %d ip addresses ", namerec->data.num_ips );
239 dbgtext( "for name %s.\n", nmb_namestr(&nmbname) );
244 for( i = 0; i < namerec->data.num_ips; i++)
246 set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags );
247 putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]);
250 /* Call the success function directly. */
252 (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec);
256 if(queue_query_name( subrec,
258 query_name_timeout_response,
266 dbgtext( "query_name: Failed to send packet " );
267 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
274 /****************************************************************************
275 Try and query for a name from nmbd acting as a WINS server.
276 ****************************************************************************/
278 BOOL query_name_from_wins_server(struct in_addr ip_to,
279 const char *name, int type,
280 query_name_success_function success_fn,
281 query_name_fail_function fail_fn,
282 struct userdata_struct *userdata)
284 struct nmb_name nmbname;
286 make_nmb_name(&nmbname, name, type);
288 if(queue_query_name_from_wins_server( ip_to,
290 query_name_timeout_response,
298 dbgtext( "query_name_from_wins_server: Failed to send packet " );
299 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );