nmbd/nmbd_namequery.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    NBT netbios routines and daemon - version 2
00004    Copyright (C) Andrew Tridgell 1994-1998
00005    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
00006    Copyright (C) Jeremy Allison 1994-2003
00007    
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012    
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017    
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021    
00022 */
00023 
00024 #include "includes.h"
00025 
00026 /****************************************************************************
00027  Deal with a response packet when querying a name.
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         /* Ensure we don't retry the query but leave the response record cleanup
00042                 to the timeout code. We may get more answer responses in which case
00043                 we should mark the name in conflict.. */
00044         rrec->repeat_count = 0;
00045 
00046         if(rrec->num_msgs == 1) {
00047                 /* This is the first response. */
00048 
00049                 if(nmb->header.opcode == NMB_WACK_OPCODE) {
00050                         /* WINS server is telling us to wait. Pretend we didn't get
00051                                 the response but don't send out any more query requests. */
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                         /* How long we should wait for. */
00062                         if (nmb->answers) {
00063                                 rrec->repeat_time = p->timestamp + nmb->answers->ttl;
00064                         } else {
00065                                 /* No answer - this is probably a corrupt
00066                                    packet.... */
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                         /* Interestingly, we could add these names to our namelists, and
00103                                 change nmbd to a model that checked its own name cache first,
00104                                 before sending out a query. This is a task for another day, though.
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                 /* We have already called the success or fail function, so we
00121                         don't call again here. Leave the response record around in
00122                         case we get more responses. */
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  Deal with a timeout when querying a name.
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         /* We can only fail here, never succeed. */
00143         BOOL failed = True;
00144         struct nmb_name *question_name = &sent_nmb->question.question_name;
00145 
00146         if(rrec->num_msgs != 0) {
00147                 /* We got at least one response, and have called the success/fail
00148                         function already. */
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  Lookup a name on our local namelists. We check the lmhosts file first. If the
00169  name is not there we look for the name on the given subnet.
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  Try and query for a name.
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          * We need to check our local namelists first.
00208          * It may be an magic name, lmhosts name or just
00209          * a name we have registered.
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                 /* Fake up the needed res_rec just in case it's used. */
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                 /* Call the success function directly. */
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  Try and query for a name from nmbd acting as a WINS server.
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 }

Sambaに対してSat Aug 29 21:23:08 2009に生成されました。  doxygen 1.4.7