00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025
00026
00027
00028
00029
00030 static void query_name_response( struct subnet_record *subrec,
00031 struct response_record *rrec,
00032 struct packet_struct *p)
00033 {
00034 struct nmb_packet *nmb = &p->packet.nmb;
00035 BOOL success = False;
00036 struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
00037 struct in_addr answer_ip;
00038
00039 zero_ip(&answer_ip);
00040
00041
00042
00043
00044 rrec->repeat_count = 0;
00045
00046 if(rrec->num_msgs == 1) {
00047
00048
00049 if(nmb->header.opcode == NMB_WACK_OPCODE) {
00050
00051
00052
00053 if( DEBUGLVL( 5 ) ) {
00054 dbgtext( "query_name_response: " );
00055 dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) );
00056 dbgtext( "in querying name %s ", nmb_namestr(question_name) );
00057 dbgtext( "on subnet %s.\n", subrec->subnet_name );
00058 }
00059
00060 rrec->repeat_count = 0;
00061
00062 if (nmb->answers) {
00063 rrec->repeat_time = p->timestamp + nmb->answers->ttl;
00064 } else {
00065
00066
00067 DEBUG(0,("query_name_response: missing answer record in "
00068 "NMB_WACK_OPCODE response.\n"));
00069 rrec->repeat_time = p->timestamp + 10;
00070 }
00071 rrec->num_msgs--;
00072 return;
00073 } else if(nmb->header.rcode != 0) {
00074
00075 success = False;
00076
00077 if( DEBUGLVL( 5 ) ) {
00078 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
00079 dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) );
00080 dbgtext( "for name %s. ", nmb_namestr(question_name) );
00081 dbgtext( "Error code was %d.\n", nmb->header.rcode );
00082 }
00083 } else {
00084 if (!nmb->answers) {
00085 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
00086 dbgtext( "IP %s ", inet_ntoa(p->ip) );
00087 dbgtext( "returned a success response with no answer\n" );
00088 return;
00089 }
00090
00091 success = True;
00092
00093 putip((char *)&answer_ip,&nmb->answers->rdata[2]);
00094
00095 if( DEBUGLVL( 5 ) ) {
00096 dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
00097 dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) );
00098 dbgtext( "for name %s. ", nmb_namestr(question_name) );
00099 dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) );
00100 }
00101
00102
00103
00104
00105
00106 }
00107 } else if( rrec->num_msgs > 1) {
00108
00109 if( DEBUGLVL( 0 ) ) {
00110 if (nmb->answers)
00111 putip( (char *)&answer_ip, &nmb->answers->rdata[2] );
00112 dbgtext( "query_name_response: " );
00113 dbgtext( "Multiple (%d) responses ", rrec->num_msgs );
00114 dbgtext( "received for a query on subnet %s ", subrec->subnet_name );
00115 dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) );
00116 dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) );
00117 dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) );
00118 }
00119
00120
00121
00122
00123
00124 return;
00125 }
00126
00127 if(success && rrec->success_fn)
00128 (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers);
00129 else if( rrec->fail_fn)
00130 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode);
00131
00132 }
00133
00134
00135
00136
00137
00138 static void query_name_timeout_response(struct subnet_record *subrec,
00139 struct response_record *rrec)
00140 {
00141 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
00142
00143 BOOL failed = True;
00144 struct nmb_name *question_name = &sent_nmb->question.question_name;
00145
00146 if(rrec->num_msgs != 0) {
00147
00148
00149
00150 failed = False;
00151 }
00152
00153 if(failed) {
00154 if( DEBUGLVL( 5 ) ) {
00155 dbgtext( "query_name_timeout_response: No response to " );
00156 dbgtext( "query for name %s ", nmb_namestr(question_name) );
00157 dbgtext( "on subnet %s.\n", subrec->subnet_name );
00158 }
00159
00160 if(rrec->fail_fn)
00161 (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0);
00162 }
00163
00164 remove_response_record(subrec, rrec);
00165 }
00166
00167
00168
00169
00170
00171
00172 static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname,
00173 struct name_record **namerecp)
00174 {
00175 struct name_record *namerec;
00176
00177 *namerecp = NULL;
00178
00179 if(find_name_in_lmhosts(nmbname, namerecp))
00180 return True;
00181
00182 if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL)
00183 return False;
00184
00185 if( NAME_IS_ACTIVE(namerec) && ( (namerec->data.source == SELF_NAME) || (namerec->data.source == LMHOSTS_NAME) ) ) {
00186 *namerecp = namerec;
00187 return True;
00188 }
00189 return False;
00190 }
00191
00192
00193
00194
00195
00196 BOOL query_name(struct subnet_record *subrec, const char *name, int type,
00197 query_name_success_function success_fn,
00198 query_name_fail_function fail_fn,
00199 struct userdata_struct *userdata)
00200 {
00201 struct nmb_name nmbname;
00202 struct name_record *namerec;
00203
00204 make_nmb_name(&nmbname, name, type);
00205
00206
00207
00208
00209
00210
00211
00212 if(query_local_namelists(subrec, &nmbname, &namerec) == True) {
00213 struct res_rec rrec;
00214 int i;
00215
00216 memset((char *)&rrec, '\0', sizeof(struct res_rec));
00217
00218
00219 rrec.rr_name = nmbname;
00220 rrec.rr_type = RR_TYPE_NB;
00221 rrec.rr_class = RR_CLASS_IN;
00222 rrec.ttl = PERMANENT_TTL;
00223 rrec.rdlength = namerec->data.num_ips * 6;
00224 if(rrec.rdlength > MAX_DGRAM_SIZE) {
00225 if( DEBUGLVL( 0 ) ) {
00226 dbgtext( "query_name: nmbd internal error - " );
00227 dbgtext( "there are %d ip addresses ", namerec->data.num_ips );
00228 dbgtext( "for name %s.\n", nmb_namestr(&nmbname) );
00229 }
00230 return False;
00231 }
00232
00233 for( i = 0; i < namerec->data.num_ips; i++) {
00234 set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags );
00235 putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]);
00236 }
00237
00238
00239 if(success_fn)
00240 (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec);
00241 return False;
00242 }
00243
00244 if(queue_query_name( subrec, query_name_response, query_name_timeout_response, success_fn, fail_fn, userdata, &nmbname) == NULL) {
00245 if( DEBUGLVL( 0 ) ) {
00246 dbgtext( "query_name: Failed to send packet " );
00247 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
00248 }
00249 return True;
00250 }
00251 return False;
00252 }
00253
00254
00255
00256
00257
00258 BOOL query_name_from_wins_server(struct in_addr ip_to,
00259 const char *name, int type,
00260 query_name_success_function success_fn,
00261 query_name_fail_function fail_fn,
00262 struct userdata_struct *userdata)
00263 {
00264 struct nmb_name nmbname;
00265
00266 make_nmb_name(&nmbname, name, type);
00267
00268 if(queue_query_name_from_wins_server( ip_to, query_name_response, query_name_timeout_response, success_fn, fail_fn, userdata, &nmbname) == NULL) {
00269 if( DEBUGLVL( 0 ) ) {
00270 dbgtext( "query_name_from_wins_server: Failed to send packet " );
00271 dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
00272 }
00273 return True;
00274 }
00275 return False;
00276 }