nmbd/nmbd_nameregister.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 /* forward declarations */
00027 static void wins_next_registration(struct response_record *rrec);
00028 
00029 
00030 /****************************************************************************
00031  Deal with a response packet when registering one of our names.
00032 ****************************************************************************/
00033 
00034 static void register_name_response(struct subnet_record *subrec,
00035                        struct response_record *rrec, struct packet_struct *p)
00036 {
00037         /* 
00038          * If we are registering broadcast, then getting a response is an
00039          * error - we do not have the name. If we are registering unicast,
00040          * then we expect to get a response.
00041          */
00042 
00043         struct nmb_packet *nmb = &p->packet.nmb;
00044         BOOL bcast = nmb->header.nm_flags.bcast;
00045         BOOL success = True;
00046         struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
00047         struct nmb_name *answer_name = &nmb->answers->rr_name;
00048         struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
00049         int ttl = 0;
00050         uint16 nb_flags = 0;
00051         struct in_addr register_ip;
00052         fstring reg_name;
00053         
00054         putip(&register_ip,&sent_nmb->additional->rdata[2]);
00055         fstrcpy(reg_name, inet_ntoa(register_ip));
00056         
00057         if (subrec == unicast_subnet) {
00058                 /* we know that this wins server is definately alive - for the moment! */
00059                 wins_srv_alive(rrec->packet->ip, register_ip);
00060         }
00061 
00062         /* Sanity check. Ensure that the answer name in the incoming packet is the
00063            same as the requested name in the outgoing packet. */
00064 
00065         if(!question_name || !answer_name) {
00066                 DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
00067                          question_name ? "question_name" : "answer_name" ));
00068                 return;
00069         }
00070 
00071         if(!nmb_name_equal(question_name, answer_name)) {
00072                 DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n", 
00073                          nmb_namestr(answer_name), nmb_namestr(question_name)));
00074                 return;
00075         }
00076 
00077         if(bcast) {
00078                 /*
00079                  * Special hack to cope with old Samba nmbd's.
00080                  * Earlier versions of Samba (up to 1.9.16p11) respond 
00081                  * to a broadcast name registration of WORKGROUP<1b> when 
00082                  * they should not. Hence, until these versions are gone, 
00083                  * we should treat such errors as success for this particular
00084                  * case only. jallison@whistle.com.
00085                  */
00086                 
00087 #if 1 /* OLD_SAMBA_SERVER_HACK */
00088                 unstring ans_name;
00089                 pull_ascii_nstring(ans_name, sizeof(ans_name), answer_name->name);
00090                 if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) &&
00091                    (answer_name->name_type == 0x1b)) {
00092                         /* Pretend we did not get this. */
00093                         rrec->num_msgs--;
00094 
00095                         DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n", 
00096                                  nmb_namestr(answer_name)));
00097                         return;
00098                 }
00099 #endif /* OLD_SAMBA_SERVER_HACK */
00100 
00101                 /* Someone else has the name. Log the problem. */
00102                 DEBUG(1,("register_name_response: Failed to register name %s IP %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n", 
00103                          nmb_namestr(answer_name), 
00104                          reg_name,
00105                          subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
00106                 success = False;
00107         } else {
00108                 /* Unicast - check to see if the response allows us to have the name. */
00109                 if (nmb->header.opcode == NMB_WACK_OPCODE) {
00110                         /* WINS server is telling us to wait. Pretend we didn't get
00111                            the response but don't send out any more register requests. */
00112 
00113                         DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n", 
00114                                  inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name));
00115 
00116                         rrec->repeat_count = 0;
00117                         /* How long we should wait for. */
00118                         rrec->repeat_time = p->timestamp + nmb->answers->ttl;
00119                         rrec->num_msgs--;
00120                         return;
00121                 } else if (nmb->header.rcode != 0) {
00122                         /* Error code - we didn't get the name. */
00123                         success = False;
00124 
00125                         DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n", 
00126                                  subrec==unicast_subnet?"WINS ":"",
00127                                  inet_ntoa(p->ip), 
00128                                  nmb_namestr(answer_name), 
00129                                  reg_name,
00130                                  nmb->header.rcode));
00131                 } else {
00132                         success = True;
00133                         /* Get the data we need to pass to the success function. */
00134                         nb_flags = get_nb_flags(nmb->answers->rdata);
00135                         ttl = nmb->answers->ttl;
00136 
00137                         /* send off a registration for the next IP, if any */
00138                         wins_next_registration(rrec);
00139                 }
00140         } 
00141 
00142         DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
00143                  success ? "success" : "failure", 
00144                  subrec==unicast_subnet?"WINS ":"",
00145                  nmb_namestr(answer_name), 
00146                  reg_name,
00147                  inet_ntoa(rrec->packet->ip)));
00148 
00149         if(success) {
00150                 /* Enter the registered name into the subnet name database before calling
00151                    the success function. */
00152                 standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
00153                 if( rrec->success_fn)
00154                         (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
00155         } else {
00156                 struct nmb_name qname = *question_name;
00157                 if( rrec->fail_fn)
00158                         (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
00159                 /* Remove the name. */
00160                 standard_fail_register( subrec, &qname);
00161         }
00162 
00163         /* Ensure we don't retry. */
00164         remove_response_record(subrec, rrec);
00165 }
00166 
00167 /****************************************************************************
00168  Deal with a timeout of a WINS registration request
00169 ****************************************************************************/
00170 
00171 static void wins_registration_timeout(struct subnet_record *subrec,
00172                                       struct response_record *rrec)
00173 {
00174         struct userdata_struct *userdata = rrec->userdata;
00175         struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
00176         struct nmb_name *nmbname = &sent_nmb->question.question_name;
00177         struct in_addr register_ip;
00178         fstring src_addr;
00179 
00180         putip(&register_ip,&sent_nmb->additional->rdata[2]);
00181 
00182         fstrcpy(src_addr, inet_ntoa(register_ip));
00183 
00184         DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n", 
00185                  inet_ntoa(rrec->packet->ip), src_addr));
00186 
00187         /* mark it temporarily dead for this source address */
00188         wins_srv_died(rrec->packet->ip, register_ip);
00189 
00190         /* if we have some userdata then use that to work out what
00191            wins server to try next */
00192         if (userdata) {
00193                 const char *tag = (const char *)userdata->data;
00194 
00195                 /* try the next wins server in our failover list for
00196                    this tag */
00197                 rrec->packet->ip = wins_srv_ip_tag(tag, register_ip);
00198         }
00199 
00200         /* if we have run out of wins servers for this tag then they
00201            must all have timed out. We treat this as *success*, not
00202            failure, and go into our standard name refresh mode. This
00203            copes with all the wins servers being down */
00204         if (wins_srv_is_dead(rrec->packet->ip, register_ip)) {
00205                 uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
00206                 int ttl = sent_nmb->additional->ttl;
00207 
00208                 standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip);
00209                 if(rrec->success_fn) {
00210                         (*(register_name_success_function)rrec->success_fn)(subrec, 
00211                                                                             rrec->userdata, 
00212                                                                             nmbname, 
00213                                                                             nb_flags, 
00214                                                                             ttl, 
00215                                                                             register_ip);
00216                 }
00217 
00218                 /* send off a registration for the next IP, if any */
00219                 wins_next_registration(rrec);
00220 
00221                 /* don't need to send this packet any more */
00222                 remove_response_record(subrec, rrec);
00223                 return;
00224         }
00225         
00226         /* we will be moving to the next WINS server for this group,
00227            send it immediately */
00228         rrec->repeat_count = 2;
00229         rrec->repeat_time = time(NULL) + 1;
00230         rrec->in_expiration_processing = False;
00231 
00232         DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
00233                  nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip)));
00234 
00235         /* notice that we don't remove the response record. This keeps
00236            us trying to register with each of our failover wins servers */
00237 }
00238 
00239 /****************************************************************************
00240  Deal with a timeout when registering one of our names.
00241 ****************************************************************************/
00242 
00243 static void register_name_timeout_response(struct subnet_record *subrec,
00244                                            struct response_record *rrec)
00245 {
00246         /*
00247          * If we are registering unicast, then NOT getting a response is an
00248          * error - we do not have the name. If we are registering broadcast,
00249          * then we don't expect to get a response.
00250          */
00251 
00252         struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
00253         BOOL bcast = sent_nmb->header.nm_flags.bcast;
00254         BOOL success = False;
00255         struct nmb_name *question_name = &sent_nmb->question.question_name;
00256         uint16 nb_flags = 0;
00257         int ttl = 0;
00258         struct in_addr registered_ip;
00259         
00260         if (bcast) {
00261                 if(rrec->num_msgs == 0) {
00262                         /* Not receiving a message is success for broadcast registration. */
00263                         success = True; 
00264 
00265                         /* Pull the success values from the original request packet. */
00266                         nb_flags = get_nb_flags(sent_nmb->additional->rdata);
00267                         ttl = sent_nmb->additional->ttl;
00268                         putip(&registered_ip,&sent_nmb->additional->rdata[2]);
00269                 }
00270         } else {
00271                 /* wins timeouts are special */
00272                 wins_registration_timeout(subrec, rrec);
00273                 return;
00274         }
00275 
00276         DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
00277                  success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
00278         if(success) {
00279                 /* Enter the registered name into the subnet name database before calling
00280                    the success function. */
00281                 standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
00282                 if( rrec->success_fn)
00283                         (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
00284         } else {
00285                 struct nmb_name qname = *question_name;
00286                 if( rrec->fail_fn)
00287                         (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
00288                 /* Remove the name. */
00289                 standard_fail_register( subrec, &qname);
00290         }
00291 
00292         /* Ensure we don't retry. */
00293         remove_response_record(subrec, rrec);
00294 }
00295 
00296 /****************************************************************************
00297  Initiate one multi-homed name registration packet.
00298 ****************************************************************************/
00299 
00300 static void multihomed_register_one(struct nmb_name *nmbname,
00301                                     uint16 nb_flags,
00302                                     register_name_success_function success_fn,
00303                                     register_name_fail_function fail_fn,
00304                                     struct in_addr ip,
00305                                     const char *tag)
00306 {
00307         struct userdata_struct *userdata;
00308         struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
00309         fstring ip_str;
00310 
00311         userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1);
00312         if (!userdata) {
00313                 DEBUG(0,("Failed to allocate userdata structure!\n"));
00314                 return;
00315         }
00316         ZERO_STRUCTP(userdata);
00317         userdata->userdata_len = strlen(tag) + 1;
00318         strlcpy(userdata->data, tag, userdata->userdata_len);   
00319 
00320         fstrcpy(ip_str, inet_ntoa(ip));
00321 
00322         DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
00323                  nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
00324 
00325         if (queue_register_multihomed_name(unicast_subnet,
00326                                            register_name_response,
00327                                            register_name_timeout_response,
00328                                            success_fn,
00329                                            fail_fn,
00330                                            userdata,
00331                                            nmbname,
00332                                            nb_flags,
00333                                            ip,
00334                                            wins_ip) == NULL) {
00335                 DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n", 
00336                          nmb_namestr(nmbname), inet_ntoa(ip)));         
00337         }
00338 
00339         free(userdata);
00340 }
00341 
00342 /****************************************************************************
00343  We have finished the registration of one IP and need to see if we have
00344  any more IPs left to register with this group of wins server for this name.
00345 ****************************************************************************/
00346 
00347 static void wins_next_registration(struct response_record *rrec)
00348 {
00349         struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
00350         struct nmb_name *nmbname = &sent_nmb->question.question_name;
00351         uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
00352         struct userdata_struct *userdata = rrec->userdata;
00353         const char *tag;
00354         struct in_addr last_ip;
00355         struct subnet_record *subrec;
00356 
00357         putip(&last_ip,&sent_nmb->additional->rdata[2]);
00358 
00359         if (!userdata) {
00360                 /* it wasn't multi-homed */
00361                 return;
00362         }
00363 
00364         tag = (const char *)userdata->data;
00365 
00366         for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00367                 if (ip_equal(last_ip, subrec->myip)) {
00368                         subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
00369                         break;
00370                 }
00371         }
00372 
00373         if (!subrec) {
00374                 /* no more to do! */
00375                 return;
00376         }
00377 
00378         switch (sent_nmb->header.opcode) {
00379         case NMB_NAME_MULTIHOMED_REG_OPCODE:
00380                 multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag);
00381                 break;
00382         case NMB_NAME_REFRESH_OPCODE_8:
00383                 queue_wins_refresh(nmbname, 
00384                                    register_name_response,
00385                                    register_name_timeout_response,
00386                                    nb_flags, subrec->myip, tag);
00387                 break;
00388         }
00389 }
00390 
00391 /****************************************************************************
00392  Try and register one of our names on the unicast subnet - multihomed.
00393 ****************************************************************************/
00394 
00395 static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
00396                                      register_name_success_function success_fn,
00397                                      register_name_fail_function fail_fn)
00398 {
00399         /*
00400           If we are adding a group name, we just send multiple
00401           register name packets to the WINS server (this is an
00402           internet group name.
00403 
00404           If we are adding a unique name, We need first to add 
00405           our names to the unicast subnet namelist. This is 
00406           because when a WINS server receives a multihomed 
00407           registration request, the first thing it does is to 
00408           send a name query to the registering machine, to see 
00409           if it has put the name in it's local namelist.
00410           We need the name there so the query response code in
00411           nmbd_incomingrequests.c will find it.
00412 
00413           We are adding this name prematurely (we don't really
00414           have it yet), but as this is on the unicast subnet
00415           only we will get away with this (only the WINS server
00416           will ever query names from us on this subnet).
00417         */
00418         int num_ips=0;
00419         int i, t;
00420         struct subnet_record *subrec;
00421         char **wins_tags;
00422         struct in_addr *ip_list;
00423         unstring name;
00424 
00425         for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
00426                 num_ips++;
00427         
00428         if((ip_list = SMB_MALLOC_ARRAY(struct in_addr, num_ips))==NULL) {
00429                 DEBUG(0,("multihomed_register_name: malloc fail !\n"));
00430                 return;
00431         }
00432 
00433         for (subrec = FIRST_SUBNET, i = 0; 
00434              subrec;
00435              subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
00436                 ip_list[i] = subrec->myip;
00437         }
00438 
00439         pull_ascii_nstring(name, sizeof(name), nmbname->name);
00440         add_name_to_subnet(unicast_subnet, name, nmbname->name_type,
00441                            nb_flags, lp_max_ttl(), SELF_NAME,
00442                            num_ips, ip_list);
00443 
00444         /* get the list of wins tags - we try to register for each of them */
00445         wins_tags = wins_srv_tags();
00446 
00447         /* Now try and register the name for each wins tag.  Note that
00448            at this point we only register our first IP with each wins
00449            group. We will register the rest from
00450            wins_next_registration() when we get the reply for this
00451            one. That follows the way W2K does things (tridge)
00452         */
00453         for (t=0; wins_tags && wins_tags[t]; t++) {
00454                 multihomed_register_one(nmbname, nb_flags,
00455                                         success_fn, fail_fn,
00456                                         ip_list[0],
00457                                         wins_tags[t]);
00458         }
00459 
00460         wins_srv_tags_free(wins_tags);
00461         
00462         SAFE_FREE(ip_list);
00463 }
00464 
00465 /****************************************************************************
00466  Try and register one of our names.
00467 ****************************************************************************/
00468 
00469 void register_name(struct subnet_record *subrec,
00470                    const char *name, int type, uint16 nb_flags,
00471                    register_name_success_function success_fn,
00472                    register_name_fail_function fail_fn,
00473                    struct userdata_struct *userdata)
00474 {
00475         struct nmb_name nmbname;
00476         nstring nname;
00477 
00478         errno = 0;
00479         push_ascii_nstring(nname, name);
00480         if (errno == E2BIG) {
00481                 unstring tname;
00482                 pull_ascii_nstring(tname, sizeof(tname), nname);
00483                 DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n",
00484                         name, tname));
00485                 make_nmb_name(&nmbname, tname, type);
00486         } else {
00487                 make_nmb_name(&nmbname, name, type);
00488         }
00489 
00490         /* Always set the NB_ACTIVE flag on the name we are
00491            registering. Doesn't make sense without it.
00492         */
00493         
00494         nb_flags |= NB_ACTIVE;
00495         
00496         if (subrec == unicast_subnet) {
00497                 /* we now always do multi-homed registration if we are
00498                    registering to a WINS server. This copes much
00499                    better with complex WINS setups */
00500                 multihomed_register_name(&nmbname, nb_flags,
00501                                          success_fn, fail_fn);
00502                 return;
00503         }
00504         
00505         if (queue_register_name(subrec,
00506                                 register_name_response,
00507                                 register_name_timeout_response,
00508                                 success_fn,
00509                                 fail_fn,
00510                                 userdata,
00511                                 &nmbname,
00512                                 nb_flags) == NULL) {
00513                 DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
00514                          nmb_namestr(&nmbname)));
00515         }
00516 }
00517 
00518 /****************************************************************************
00519  Try and refresh one of our names. This is *only* called for WINS refresh
00520 ****************************************************************************/
00521 
00522 void wins_refresh_name(struct name_record *namerec)
00523 {
00524         int t;
00525         char **wins_tags;
00526 
00527         /* get the list of wins tags - we try to refresh for each of them */
00528         wins_tags = wins_srv_tags();
00529 
00530         for (t=0; wins_tags && wins_tags[t]; t++) {
00531                 queue_wins_refresh(&namerec->name, 
00532                                    register_name_response,
00533                                    register_name_timeout_response,
00534                                    namerec->data.nb_flags,
00535                                    namerec->data.ip[0], wins_tags[t]);
00536         }
00537 
00538         wins_srv_tags_free(wins_tags);
00539 }

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