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 putip((char *)&answer_ip
,&nmb
->answers
->rdata
[2]);
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)
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. */
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. */
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
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
);
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
;
175 if(find_name_in_lmhosts(nmbname
, namerecp
))
178 if((namerec
= find_name_on_subnet(subrec
, nmbname
, FIND_ANY_NAME
))==NULL
)
181 if( NAME_IS_ACTIVE(namerec
)
182 && ( (namerec
->data
.source
== SELF_NAME
)
183 || (namerec
->data
.source
== LMHOSTS_NAME
) ) )
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
)
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
)
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
) );
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. */
243 (*(query_name_success_function
)success_fn
)(subrec
, userdata
, &nmbname
, namerec
->data
.ip
[0], &rrec
);
247 if(queue_query_name( subrec
,
249 query_name_timeout_response
,
257 dbgtext( "query_name: Failed to send packet " );
258 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname
) );
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
,
281 query_name_timeout_response
,
289 dbgtext( "query_name_from_wins_server: Failed to send packet " );
290 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname
) );