2 Unix SMB/Netbios implementation.
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.
27 extern int DEBUGLEVEL;
28 extern struct in_addr ipzero;
30 /****************************************************************************
31 Deal with a response packet when querying a name.
32 ****************************************************************************/
34 static void query_name_response( struct subnet_record *subrec,
35 struct response_record *rrec,
36 struct packet_struct *p)
38 struct nmb_packet *nmb = &p->packet.nmb;
40 struct nmb_name *question_name =
41 &rrec->packet->packet.nmb.question.question_name;
42 struct in_addr answer_ip = ipzero;
44 /* Ensure we don't retry the query but leave the response record cleanup
45 to the timeout code. We may get more answer responses in which case
46 we should mark the name in conflict.. */
47 rrec->repeat_count = 0;
49 if(rrec->num_msgs == 1)
51 /* This is the first response. */
53 if(nmb->header.opcode == NMB_WACK_OPCODE)
55 /* WINS server is telling us to wait. Pretend we didn't get
56 the response but don't send out any more query requests. */
60 dbgtext( "query_name_response: " );
61 dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) );
62 dbgtext( "in querying name %s ", nmb_namestr(question_name) );
63 dbgtext( "on subnet %s.\n", subrec->subnet_name );
66 rrec->repeat_count = 0;
67 /* How long we should wait for. */
68 rrec->repeat_time = p->timestamp + nmb->answers->ttl;
72 else if(nmb->header.rcode != 0)
78 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
79 dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) );
80 dbgtext( "for name %s. ", nmb_namestr(question_name) );
81 dbgtext( "Error code was %d.\n", nmb->header.rcode );
88 putip((char *)&answer_ip,&nmb->answers->rdata[2]);
91 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
92 dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) );
93 dbgtext( "for name %s. ", nmb_namestr(question_name) );
94 dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) );
97 /* Interestingly, we could add these names to our namelists, and
98 change nmbd to a model that checked its own name cache first,
99 before sending out a query. This is a task for another day, though.
103 else if( rrec->num_msgs > 1)
107 putip( (char *)&answer_ip, &nmb->answers->rdata[2] );
108 dbgtext( "query_name_response: " );
109 dbgtext( "Multiple (%d) responses ", rrec->num_msgs );
110 dbgtext( "received for a query on subnet %s ", subrec->subnet_name );
111 dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) );
112 dbgtext( "was from IP %s, reporting", inet_ntoa(p->ip) );
113 dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) );
116 /* We have already called the success or fail function, so we
117 don't call again here. Leave the response record around in
118 case we get more responses. */
123 if(success && rrec->success_fn)
124 (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers);
125 else if( rrec->fail_fn)
126 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode);
130 /****************************************************************************
131 Deal with a timeout when querying a name.
132 ****************************************************************************/
134 static void query_name_timeout_response(struct subnet_record *subrec,
135 struct response_record *rrec)
137 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
138 /* We can only fail here, never succeed. */
140 struct nmb_name *question_name = &sent_nmb->question.question_name;
142 if(rrec->num_msgs != 0)
144 /* We got at least one response, and have called the success/fail
154 dbgtext( "query_name_timeout_response: No response to " );
155 dbgtext( "query for name %s ", nmb_namestr(question_name) );
156 dbgtext( "on subnet %s.\n", subrec->subnet_name );
159 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0);
162 remove_response_record(subrec, rrec);
165 /****************************************************************************
166 Lookup a name on our local namelists. We check the lmhosts file first. If the
167 name is not there we look for the name on the given subnet.
168 ****************************************************************************/
170 static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname,
171 struct name_record **namerecp)
173 struct name_record *namerec;
177 if(find_name_in_lmhosts(nmbname, namerecp))
180 if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL)
183 if( NAME_IS_ACTIVE(namerec)
184 && ( (namerec->data.source == SELF_NAME)
185 || (namerec->data.source == LMHOSTS_NAME) ) )
193 /****************************************************************************
194 Try and query for a name.
195 ****************************************************************************/
197 BOOL query_name(struct subnet_record *subrec, char *name, int type,
198 query_name_success_function success_fn,
199 query_name_fail_function fail_fn,
200 struct userdata_struct *userdata)
202 struct nmb_name nmbname;
203 struct name_record *namerec;
205 make_nmb_name(&nmbname, name, type);
208 * We need to check our local namelists first.
209 * It may be an magic name, lmhosts name or just
210 * a name we have registered.
213 if(query_local_namelists(subrec, &nmbname, &namerec) == True)
218 memset((char *)&rrec, '\0', sizeof(struct res_rec));
220 /* Fake up the needed res_rec just in case it's used. */
221 rrec.rr_name = nmbname;
222 rrec.rr_type = RR_TYPE_NB;
223 rrec.rr_class = RR_CLASS_IN;
224 rrec.ttl = PERMANENT_TTL;
225 rrec.rdlength = namerec->data.num_ips * 6;
226 if(rrec.rdlength > MAX_DGRAM_SIZE)
230 dbgtext( "query_name: nmbd internal error - " );
231 dbgtext( "there are %d ip addresses ", namerec->data.num_ips );
232 dbgtext( "for name %s.\n", nmb_namestr(&nmbname) );
237 for( i = 0; i < namerec->data.num_ips; i++)
239 set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags );
240 putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]);
243 /* Call the success function directly. */
245 (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec);
249 if(queue_query_name( subrec,
251 query_name_timeout_response,
259 dbgtext( "query_name: Failed to send packet " );
260 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
267 /****************************************************************************
268 Try and query for a name from nmbd acting as a WINS server.
269 ****************************************************************************/
271 BOOL query_name_from_wins_server(struct in_addr ip_to,
272 char *name, int type,
273 query_name_success_function success_fn,
274 query_name_fail_function fail_fn,
275 struct userdata_struct *userdata)
277 struct nmb_name nmbname;
279 make_nmb_name(&nmbname, name, type);
281 if(queue_query_name_from_wins_server( ip_to,
283 query_name_timeout_response,
291 dbgtext( "query_name_from_wins_server: Failed to send packet " );
292 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );