new WHATSNEW for 2.2.7
[Samba.git] / source / nmbd / nmbd_namequery.c
blob945058d2b2bd8069ef886b7316ab599c03e38317
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1998
6 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
7 Copyright (C) Jeremy Allison 1994-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
27 /****************************************************************************
28 Deal with a response packet when querying a name.
29 ****************************************************************************/
31 static void query_name_response( struct subnet_record *subrec,
32 struct response_record *rrec,
33 struct packet_struct *p)
35 struct nmb_packet *nmb = &p->packet.nmb;
36 BOOL success = False;
37 struct nmb_name *question_name =
38 &rrec->packet->packet.nmb.question.question_name;
39 struct in_addr answer_ip;
41 zero_ip(&answer_ip);
43 /* Ensure we don't retry the query but leave the response record cleanup
44 to the timeout code. We may get more answer responses in which case
45 we should mark the name in conflict.. */
46 rrec->repeat_count = 0;
48 if(rrec->num_msgs == 1)
50 /* This is the first response. */
52 if(nmb->header.opcode == NMB_WACK_OPCODE)
54 /* WINS server is telling us to wait. Pretend we didn't get
55 the response but don't send out any more query requests. */
57 if( DEBUGLVL( 5 ) )
59 dbgtext( "query_name_response: " );
60 dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) );
61 dbgtext( "in querying name %s ", nmb_namestr(question_name) );
62 dbgtext( "on subnet %s.\n", subrec->subnet_name );
65 rrec->repeat_count = 0;
66 /* How long we should wait for. */
67 rrec->repeat_time = p->timestamp + nmb->answers->ttl;
68 rrec->num_msgs--;
69 return;
71 else if(nmb->header.rcode != 0)
73 success = False;
75 if( DEBUGLVL( 5 ) )
77 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
78 dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) );
79 dbgtext( "for name %s. ", nmb_namestr(question_name) );
80 dbgtext( "Error code was %d.\n", nmb->header.rcode );
83 else
85 success = True;
87 putip((char *)&answer_ip,&nmb->answers->rdata[2]);
88 if( DEBUGLVL( 5 ) )
90 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
91 dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) );
92 dbgtext( "for name %s. ", nmb_namestr(question_name) );
93 dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) );
96 /* Interestingly, we could add these names to our namelists, and
97 change nmbd to a model that checked its own name cache first,
98 before sending out a query. This is a task for another day, though.
102 else if( rrec->num_msgs > 1)
104 if( DEBUGLVL( 0 ) )
106 putip( (char *)&answer_ip, &nmb->answers->rdata[2] );
107 dbgtext( "query_name_response: " );
108 dbgtext( "Multiple (%d) responses ", rrec->num_msgs );
109 dbgtext( "received for a query on subnet %s ", subrec->subnet_name );
110 dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) );
111 dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) );
112 dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) );
115 /* We have already called the success or fail function, so we
116 don't call again here. Leave the response record around in
117 case we get more responses. */
119 return;
122 if(success && rrec->success_fn)
123 (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers);
124 else if( rrec->fail_fn)
125 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode);
129 /****************************************************************************
130 Deal with a timeout when querying a name.
131 ****************************************************************************/
133 static void query_name_timeout_response(struct subnet_record *subrec,
134 struct response_record *rrec)
136 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
137 /* We can only fail here, never succeed. */
138 BOOL failed = True;
139 struct nmb_name *question_name = &sent_nmb->question.question_name;
141 if(rrec->num_msgs != 0)
143 /* We got at least one response, and have called the success/fail
144 function already. */
146 failed = False;
149 if(failed)
151 if( DEBUGLVL( 5 ) )
153 dbgtext( "query_name_timeout_response: No response to " );
154 dbgtext( "query for name %s ", nmb_namestr(question_name) );
155 dbgtext( "on subnet %s.\n", subrec->subnet_name );
157 if(rrec->fail_fn)
158 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0);
161 remove_response_record(subrec, rrec);
164 /****************************************************************************
165 Lookup a name on our local namelists. We check the lmhosts file first. If the
166 name is not there we look for the name on the given subnet.
167 ****************************************************************************/
169 static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname,
170 struct name_record **namerecp)
172 struct name_record *namerec;
174 *namerecp = NULL;
176 if(find_name_in_lmhosts(nmbname, namerecp))
177 return True;
179 if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL)
180 return False;
182 if( NAME_IS_ACTIVE(namerec)
183 && ( (namerec->data.source == SELF_NAME)
184 || (namerec->data.source == LMHOSTS_NAME) ) )
186 *namerecp = namerec;
187 return True;
189 return False;
192 /****************************************************************************
193 Try and query for a name.
194 ****************************************************************************/
196 BOOL query_name(struct subnet_record *subrec, char *name, int type,
197 query_name_success_function success_fn,
198 query_name_fail_function fail_fn,
199 struct userdata_struct *userdata)
201 struct nmb_name nmbname;
202 struct name_record *namerec;
204 make_nmb_name(&nmbname, name, type);
207 * We need to check our local namelists first.
208 * It may be an magic name, lmhosts name or just
209 * a name we have registered.
212 if(query_local_namelists(subrec, &nmbname, &namerec) == True)
214 struct res_rec rrec;
215 int i;
217 memset((char *)&rrec, '\0', sizeof(struct res_rec));
219 /* Fake up the needed res_rec just in case it's used. */
220 rrec.rr_name = nmbname;
221 rrec.rr_type = RR_TYPE_NB;
222 rrec.rr_class = RR_CLASS_IN;
223 rrec.ttl = PERMANENT_TTL;
224 rrec.rdlength = namerec->data.num_ips * 6;
225 if(rrec.rdlength > MAX_DGRAM_SIZE)
227 if( DEBUGLVL( 0 ) )
229 dbgtext( "query_name: nmbd internal error - " );
230 dbgtext( "there are %d ip addresses ", namerec->data.num_ips );
231 dbgtext( "for name %s.\n", nmb_namestr(&nmbname) );
233 return False;
236 for( i = 0; i < namerec->data.num_ips; i++)
238 set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags );
239 putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]);
242 /* Call the success function directly. */
243 if(success_fn)
244 (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec);
245 return False;
248 if(queue_query_name( subrec,
249 query_name_response,
250 query_name_timeout_response,
251 success_fn,
252 fail_fn,
253 userdata,
254 &nmbname) == NULL)
256 if( DEBUGLVL( 0 ) )
258 dbgtext( "query_name: Failed to send packet " );
259 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
261 return True;
263 return False;
266 /****************************************************************************
267 Try and query for a name from nmbd acting as a WINS server.
268 ****************************************************************************/
270 BOOL query_name_from_wins_server(struct in_addr ip_to,
271 char *name, int type,
272 query_name_success_function success_fn,
273 query_name_fail_function fail_fn,
274 struct userdata_struct *userdata)
276 struct nmb_name nmbname;
278 make_nmb_name(&nmbname, name, type);
280 if(queue_query_name_from_wins_server( ip_to,
281 query_name_response,
282 query_name_timeout_response,
283 success_fn,
284 fail_fn,
285 userdata,
286 &nmbname) == NULL)
288 if( DEBUGLVL( 0 ) )
290 dbgtext( "query_name_from_wins_server: Failed to send packet " );
291 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
293 return True;
295 return False;