merge from APPLIANCE_HEAD
[Samba.git] / source / nmbd / nmbd_namequery.c
blobaeb9984180de90e38656a1c68f7dff057a289d0c
1 /*
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.
24 #include "includes.h"
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;
35 BOOL success = False;
36 struct nmb_name *question_name =
37 &rrec->packet->packet.nmb.question.question_name;
38 struct in_addr answer_ip;
40 zero_ip(&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. */
56 if( DEBUGLVL( 5 ) )
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;
67 rrec->num_msgs--;
68 return;
70 else if(nmb->header.rcode != 0)
72 success = False;
74 if( DEBUGLVL( 5 ) )
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 );
82 else
84 success = True;
86 putip((char *)&answer_ip,&nmb->answers->rdata[2]);
87 if( DEBUGLVL( 5 ) )
89 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
90 dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) );
91 dbgtext( "for name %s. ", nmb_namestr(question_name) );
92 dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) );
95 /* Interestingly, we could add these names to our namelists, and
96 change nmbd to a model that checked its own name cache first,
97 before sending out a query. This is a task for another day, though.
101 else if( rrec->num_msgs > 1)
103 if( DEBUGLVL( 0 ) )
105 putip( (char *)&answer_ip, &nmb->answers->rdata[2] );
106 dbgtext( "query_name_response: " );
107 dbgtext( "Multiple (%d) responses ", rrec->num_msgs );
108 dbgtext( "received for a query on subnet %s ", subrec->subnet_name );
109 dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) );
110 dbgtext( "was from IP %s, reporting", inet_ntoa(p->ip) );
111 dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) );
114 /* We have already called the success or fail function, so we
115 don't call again here. Leave the response record around in
116 case we get more responses. */
118 return;
121 if(success && rrec->success_fn)
122 (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers);
123 else if( rrec->fail_fn)
124 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode);
128 /****************************************************************************
129 Deal with a timeout when querying a name.
130 ****************************************************************************/
132 static void query_name_timeout_response(struct subnet_record *subrec,
133 struct response_record *rrec)
135 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
136 /* We can only fail here, never succeed. */
137 BOOL failed = True;
138 struct nmb_name *question_name = &sent_nmb->question.question_name;
140 if(rrec->num_msgs != 0)
142 /* We got at least one response, and have called the success/fail
143 function already. */
145 failed = False;
148 if(failed)
150 if( DEBUGLVL( 5 ) )
152 dbgtext( "query_name_timeout_response: No response to " );
153 dbgtext( "query for name %s ", nmb_namestr(question_name) );
154 dbgtext( "on subnet %s.\n", subrec->subnet_name );
156 if(rrec->fail_fn)
157 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0);
160 remove_response_record(subrec, rrec);
163 /****************************************************************************
164 Lookup a name on our local namelists. We check the lmhosts file first. If the
165 name is not there we look for the name on the given subnet.
166 ****************************************************************************/
168 static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname,
169 struct name_record **namerecp)
171 struct name_record *namerec;
173 *namerecp = NULL;
175 if(find_name_in_lmhosts(nmbname, namerecp))
176 return True;
178 if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL)
179 return False;
181 if( NAME_IS_ACTIVE(namerec)
182 && ( (namerec->data.source == SELF_NAME)
183 || (namerec->data.source == LMHOSTS_NAME) ) )
185 *namerecp = namerec;
186 return True;
188 return False;
191 /****************************************************************************
192 Try and query for a name.
193 ****************************************************************************/
195 BOOL query_name(struct subnet_record *subrec, char *name, int type,
196 query_name_success_function success_fn,
197 query_name_fail_function fail_fn,
198 struct userdata_struct *userdata)
200 struct nmb_name nmbname;
201 struct name_record *namerec;
203 make_nmb_name(&nmbname, name, type);
206 * We need to check our local namelists first.
207 * It may be an magic name, lmhosts name or just
208 * a name we have registered.
211 if(query_local_namelists(subrec, &nmbname, &namerec) == True)
213 struct res_rec rrec;
214 int i;
216 memset((char *)&rrec, '\0', sizeof(struct res_rec));
218 /* Fake up the needed res_rec just in case it's used. */
219 rrec.rr_name = nmbname;
220 rrec.rr_type = RR_TYPE_NB;
221 rrec.rr_class = RR_CLASS_IN;
222 rrec.ttl = PERMANENT_TTL;
223 rrec.rdlength = namerec->data.num_ips * 6;
224 if(rrec.rdlength > MAX_DGRAM_SIZE)
226 if( DEBUGLVL( 0 ) )
228 dbgtext( "query_name: nmbd internal error - " );
229 dbgtext( "there are %d ip addresses ", namerec->data.num_ips );
230 dbgtext( "for name %s.\n", nmb_namestr(&nmbname) );
232 return False;
235 for( i = 0; i < namerec->data.num_ips; i++)
237 set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags );
238 putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]);
241 /* Call the success function directly. */
242 if(success_fn)
243 (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec);
244 return False;
247 if(queue_query_name( subrec,
248 query_name_response,
249 query_name_timeout_response,
250 success_fn,
251 fail_fn,
252 userdata,
253 &nmbname) == NULL)
255 if( DEBUGLVL( 0 ) )
257 dbgtext( "query_name: Failed to send packet " );
258 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
260 return True;
262 return False;
265 /****************************************************************************
266 Try and query for a name from nmbd acting as a WINS server.
267 ****************************************************************************/
269 BOOL query_name_from_wins_server(struct in_addr ip_to,
270 char *name, int type,
271 query_name_success_function success_fn,
272 query_name_fail_function fail_fn,
273 struct userdata_struct *userdata)
275 struct nmb_name nmbname;
277 make_nmb_name(&nmbname, name, type);
279 if(queue_query_name_from_wins_server( ip_to,
280 query_name_response,
281 query_name_timeout_response,
282 success_fn,
283 fail_fn,
284 userdata,
285 &nmbname) == NULL)
287 if( DEBUGLVL( 0 ) )
289 dbgtext( "query_name_from_wins_server: Failed to send packet " );
290 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
292 return True;
294 return False;