r492: BUG 483: patch from Michel Gravey <michel.gravey@optogone.com> to fix password...
[Samba/gebeck_regimport.git] / source3 / nmbd / nmbd_namequery.c
blob1b07852f111b9e5415a6285b5049822e80ebef31
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-2003
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 = &rrec->packet->packet.nmb.question.question_name;
37 struct in_addr answer_ip;
39 zero_ip(&answer_ip);
41 /* Ensure we don't retry the query but leave the response record cleanup
42 to the timeout code. We may get more answer responses in which case
43 we should mark the name in conflict.. */
44 rrec->repeat_count = 0;
46 if(rrec->num_msgs == 1) {
47 /* This is the first response. */
49 if(nmb->header.opcode == NMB_WACK_OPCODE) {
50 /* WINS server is telling us to wait. Pretend we didn't get
51 the response but don't send out any more query requests. */
53 if( DEBUGLVL( 5 ) ) {
54 dbgtext( "query_name_response: " );
55 dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) );
56 dbgtext( "in querying name %s ", nmb_namestr(question_name) );
57 dbgtext( "on subnet %s.\n", subrec->subnet_name );
60 rrec->repeat_count = 0;
61 /* How long we should wait for. */
62 rrec->repeat_time = p->timestamp + nmb->answers->ttl;
63 rrec->num_msgs--;
64 return;
65 } else if(nmb->header.rcode != 0) {
67 success = False;
69 if( DEBUGLVL( 5 ) ) {
70 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
71 dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) );
72 dbgtext( "for name %s. ", nmb_namestr(question_name) );
73 dbgtext( "Error code was %d.\n", nmb->header.rcode );
75 } else {
76 if (!nmb->answers) {
77 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
78 dbgtext( "IP %s ", inet_ntoa(p->ip) );
79 dbgtext( "returned a success response with no answer\n" );
80 return;
83 success = True;
85 putip((char *)&answer_ip,&nmb->answers->rdata[2]);
87 if( DEBUGLVL( 5 ) ) {
88 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
89 dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) );
90 dbgtext( "for name %s. ", nmb_namestr(question_name) );
91 dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) );
94 /* Interestingly, we could add these names to our namelists, and
95 change nmbd to a model that checked its own name cache first,
96 before sending out a query. This is a task for another day, though.
99 } else if( rrec->num_msgs > 1) {
101 if( DEBUGLVL( 0 ) ) {
102 if (nmb->answers)
103 putip( (char *)&answer_ip, &nmb->answers->rdata[2] );
104 dbgtext( "query_name_response: " );
105 dbgtext( "Multiple (%d) responses ", rrec->num_msgs );
106 dbgtext( "received for a query on subnet %s ", subrec->subnet_name );
107 dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) );
108 dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) );
109 dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) );
112 /* We have already called the success or fail function, so we
113 don't call again here. Leave the response record around in
114 case we get more responses. */
116 return;
119 if(success && rrec->success_fn)
120 (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers);
121 else if( rrec->fail_fn)
122 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode);
126 /****************************************************************************
127 Deal with a timeout when querying a name.
128 ****************************************************************************/
130 static void query_name_timeout_response(struct subnet_record *subrec,
131 struct response_record *rrec)
133 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
134 /* We can only fail here, never succeed. */
135 BOOL failed = True;
136 struct nmb_name *question_name = &sent_nmb->question.question_name;
138 if(rrec->num_msgs != 0) {
139 /* We got at least one response, and have called the success/fail
140 function already. */
142 failed = False;
145 if(failed) {
146 if( DEBUGLVL( 5 ) ) {
147 dbgtext( "query_name_timeout_response: No response to " );
148 dbgtext( "query for name %s ", nmb_namestr(question_name) );
149 dbgtext( "on subnet %s.\n", subrec->subnet_name );
152 if(rrec->fail_fn)
153 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0);
156 remove_response_record(subrec, rrec);
159 /****************************************************************************
160 Lookup a name on our local namelists. We check the lmhosts file first. If the
161 name is not there we look for the name on the given subnet.
162 ****************************************************************************/
164 static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname,
165 struct name_record **namerecp)
167 struct name_record *namerec;
169 *namerecp = NULL;
171 if(find_name_in_lmhosts(nmbname, namerecp))
172 return True;
174 if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL)
175 return False;
177 if( NAME_IS_ACTIVE(namerec) && ( (namerec->data.source == SELF_NAME) || (namerec->data.source == LMHOSTS_NAME) ) ) {
178 *namerecp = namerec;
179 return True;
181 return False;
184 /****************************************************************************
185 Try and query for a name.
186 ****************************************************************************/
188 BOOL query_name(struct subnet_record *subrec, const char *name, int type,
189 query_name_success_function success_fn,
190 query_name_fail_function fail_fn,
191 struct userdata_struct *userdata)
193 struct nmb_name nmbname;
194 struct name_record *namerec;
196 make_nmb_name(&nmbname, name, type);
199 * We need to check our local namelists first.
200 * It may be an magic name, lmhosts name or just
201 * a name we have registered.
204 if(query_local_namelists(subrec, &nmbname, &namerec) == True) {
205 struct res_rec rrec;
206 int i;
208 memset((char *)&rrec, '\0', sizeof(struct res_rec));
210 /* Fake up the needed res_rec just in case it's used. */
211 rrec.rr_name = nmbname;
212 rrec.rr_type = RR_TYPE_NB;
213 rrec.rr_class = RR_CLASS_IN;
214 rrec.ttl = PERMANENT_TTL;
215 rrec.rdlength = namerec->data.num_ips * 6;
216 if(rrec.rdlength > MAX_DGRAM_SIZE) {
217 if( DEBUGLVL( 0 ) ) {
218 dbgtext( "query_name: nmbd internal error - " );
219 dbgtext( "there are %d ip addresses ", namerec->data.num_ips );
220 dbgtext( "for name %s.\n", nmb_namestr(&nmbname) );
222 return False;
225 for( i = 0; i < namerec->data.num_ips; i++) {
226 set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags );
227 putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]);
230 /* Call the success function directly. */
231 if(success_fn)
232 (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec);
233 return False;
236 if(queue_query_name( subrec, query_name_response, query_name_timeout_response, success_fn, fail_fn, userdata, &nmbname) == NULL) {
237 if( DEBUGLVL( 0 ) ) {
238 dbgtext( "query_name: Failed to send packet " );
239 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
241 return True;
243 return False;
246 /****************************************************************************
247 Try and query for a name from nmbd acting as a WINS server.
248 ****************************************************************************/
250 BOOL query_name_from_wins_server(struct in_addr ip_to,
251 const char *name, int type,
252 query_name_success_function success_fn,
253 query_name_fail_function fail_fn,
254 struct userdata_struct *userdata)
256 struct nmb_name nmbname;
258 make_nmb_name(&nmbname, name, type);
260 if(queue_query_name_from_wins_server( ip_to, query_name_response, query_name_timeout_response, success_fn, fail_fn, userdata, &nmbname) == NULL) {
261 if( DEBUGLVL( 0 ) ) {
262 dbgtext( "query_name_from_wins_server: Failed to send packet " );
263 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
265 return True;
267 return False;