nmbd/nmbd_subnetdb.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-1998
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    Revision History:
00023 
00024 */
00025 
00026 #include "includes.h"
00027 
00028 extern struct in_addr loopback_ip;
00029 extern int global_nmb_port;
00030 
00031 /* This is the broadcast subnets database. */
00032 struct subnet_record *subnetlist = NULL;
00033 
00034 /* Extra subnets - keep these separate so enumeration code doesn't
00035    run onto it by mistake. */
00036 
00037 struct subnet_record *unicast_subnet = NULL;
00038 struct subnet_record *remote_broadcast_subnet = NULL;
00039 struct subnet_record *wins_server_subnet = NULL;
00040 
00041 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
00042 
00043 /****************************************************************************
00044   Add a subnet into the list.
00045   **************************************************************************/
00046 
00047 static void add_subnet(struct subnet_record *subrec)
00048 {
00049         DLIST_ADD(subnetlist, subrec);
00050 }
00051 
00052 /****************************************************************************
00053 stop listening on a subnet
00054 we don't free the record as we don't have proper reference counting for it
00055 yet and it may be in use by a response record
00056   ****************************************************************************/
00057 
00058 void close_subnet(struct subnet_record *subrec)
00059 {
00060         if (subrec->dgram_sock != -1) {
00061                 close(subrec->dgram_sock);
00062                 subrec->dgram_sock = -1;
00063         }
00064         if (subrec->nmb_sock != -1) {
00065                 close(subrec->nmb_sock);
00066                 subrec->nmb_sock = -1;
00067         }
00068 
00069         DLIST_REMOVE(subnetlist, subrec);
00070 }
00071 
00072 /****************************************************************************
00073   Create a subnet entry.
00074   ****************************************************************************/
00075 
00076 static struct subnet_record *make_subnet(const char *name, enum subnet_type type,
00077                                          struct in_addr myip, struct in_addr bcast_ip, 
00078                                          struct in_addr mask_ip)
00079 {
00080         struct subnet_record *subrec = NULL;
00081         int nmb_sock, dgram_sock;
00082 
00083         /* Check if we are creating a non broadcast subnet - if so don't create
00084                 sockets.  */
00085 
00086         if(type != NORMAL_SUBNET) {
00087                 nmb_sock = -1;
00088                 dgram_sock = -1;
00089         } else {
00090                 /*
00091                  * Attempt to open the sockets on port 137/138 for this interface
00092                  * and bind them.
00093                  * Fail the subnet creation if this fails.
00094                  */
00095 
00096                 if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) {
00097                         if( DEBUGLVL( 0 ) ) {
00098                                 Debug1( "nmbd_subnetdb:make_subnet()\n" );
00099                                 Debug1( "  Failed to open nmb socket on interface %s ", inet_ntoa(myip) );
00100                                 Debug1( "for port %d.  ", global_nmb_port );
00101                                 Debug1( "Error was %s\n", strerror(errno) );
00102                         }
00103                         return NULL;
00104                 }
00105 
00106                 if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) {
00107                         if( DEBUGLVL( 0 ) ) {
00108                                 Debug1( "nmbd_subnetdb:make_subnet()\n" );
00109                                 Debug1( "  Failed to open dgram socket on interface %s ", inet_ntoa(myip) );
00110                                 Debug1( "for port %d.  ", DGRAM_PORT );
00111                                 Debug1( "Error was %s\n", strerror(errno) );
00112                         }
00113                         return NULL;
00114                 }
00115 
00116                 /* Make sure we can broadcast from these sockets. */
00117                 set_socket_options(nmb_sock,"SO_BROADCAST");
00118                 set_socket_options(dgram_sock,"SO_BROADCAST");
00119 
00120                 /* Set them non-blocking. */
00121                 set_blocking(nmb_sock, False);
00122                 set_blocking(dgram_sock, False);
00123         }
00124 
00125         subrec = SMB_MALLOC_P(struct subnet_record);
00126         if (!subrec) {
00127                 DEBUG(0,("make_subnet: malloc fail !\n"));
00128                 close(nmb_sock);
00129                 close(dgram_sock);
00130                 return(NULL);
00131         }
00132   
00133         ZERO_STRUCTP(subrec);
00134 
00135         if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
00136                 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
00137                 close(nmb_sock);
00138                 close(dgram_sock);
00139                 ZERO_STRUCTP(subrec);
00140                 SAFE_FREE(subrec);
00141                 return(NULL);
00142         }
00143 
00144         DEBUG(2, ("making subnet name:%s ", name ));
00145         DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
00146         DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
00147  
00148         subrec->namelist_changed = False;
00149         subrec->work_changed = False;
00150  
00151         subrec->bcast_ip = bcast_ip;
00152         subrec->mask_ip  = mask_ip;
00153         subrec->myip = myip;
00154         subrec->type = type;
00155         subrec->nmb_sock = nmb_sock;
00156         subrec->dgram_sock = dgram_sock;
00157   
00158         return subrec;
00159 }
00160 
00161 /****************************************************************************
00162   Create a normal subnet
00163 **************************************************************************/
00164 
00165 struct subnet_record *make_normal_subnet(struct interface *iface)
00166 {
00167         struct subnet_record *subrec;
00168 
00169         subrec = make_subnet(inet_ntoa(iface->ip), NORMAL_SUBNET,
00170                              iface->ip, iface->bcast, iface->nmask);
00171         if (subrec) {
00172                 add_subnet(subrec);
00173         }
00174         return subrec;
00175 }
00176 
00177 /****************************************************************************
00178   Create subnet entries.
00179 **************************************************************************/
00180 
00181 BOOL create_subnets(void)
00182 {    
00183         int num_interfaces;
00184         int i;
00185         struct in_addr unicast_ip, ipzero;
00186 
00187   try_interfaces_again:
00188 
00189         if (iface_count_nl() == 0) {
00190                 DEBUG(0,("create_subnets: No non-loopback local interfaces !\n"));
00191                 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
00192         }
00193 
00194         while (iface_count_nl() == 0) {
00195                 void (*saved_handler)(int);
00196 
00197                 /* 
00198                  * Whilst we're waiting for an interface, allow SIGTERM to
00199                  * cause us to exit.
00200                  */
00201 
00202                 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
00203 
00204                 sleep(5);
00205                 load_interfaces();
00206 
00207                 /* 
00208                  * We got an interface, restore our normal term handler.
00209                  */
00210 
00211                 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
00212         }
00213 
00214         num_interfaces = iface_count();
00215 
00216         /* 
00217          * Create subnets from all the local interfaces and thread them onto
00218          * the linked list. 
00219          */
00220 
00221         for (i = 0 ; i < num_interfaces; i++) {
00222                 struct interface *iface = get_interface(i);
00223 
00224                 if (!iface) {
00225                         DEBUG(2,("create_subnets: can't get interface %d.\n", i ));
00226                         continue;
00227                 }
00228 
00229                 /*
00230                  * We don't want to add a loopback interface, in case
00231                  * someone has added 127.0.0.1 for smbd, nmbd needs to
00232                  * ignore it here. JRA.
00233                  */
00234 
00235                 if (ip_equal(iface->ip, loopback_ip)) {
00236                         DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
00237                         continue;
00238                 }
00239 
00240                 if (!make_normal_subnet(iface))
00241                         return False;
00242         }
00243 
00244         /* We must have at least one subnet. */
00245         if (subnetlist == NULL) {
00246                 void (*saved_handler)(int);
00247 
00248                 DEBUG(0,("create_subnets: Unable to create any subnet from "
00249                                 "given interfaces. Is your interface line in "
00250                                 "smb.conf correct ?\n"));
00251 
00252                 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
00253 
00254                 sleep(5);
00255                 load_interfaces();
00256 
00257                 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
00258                 goto try_interfaces_again;
00259         }
00260 
00261         if (lp_we_are_a_wins_server()) {
00262                 /* Pick the first interface ip address as the WINS server ip. */
00263                 struct in_addr *nip = iface_n_ip(0);
00264 
00265                 if (!nip) {
00266                         return False;
00267                 }
00268 
00269                 unicast_ip = *nip;
00270         } else {
00271                 /* note that we do not set the wins server IP here. We just
00272                         set it at zero and let the wins registration code cope
00273                         with getting the IPs right for each packet */
00274                 zero_ip(&unicast_ip);
00275         }
00276 
00277         /*
00278          * Create the unicast and remote broadcast subnets.
00279          * Don't put these onto the linked list.
00280          * The ip address of the unicast subnet is set to be
00281          * the WINS server address, if it exists, or ipzero if not.
00282          */
00283 
00284         unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, 
00285                                 unicast_ip, unicast_ip, unicast_ip);
00286 
00287         zero_ip(&ipzero);
00288 
00289         remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
00290                                 REMOTE_BROADCAST_SUBNET,
00291                                 ipzero, ipzero, ipzero);
00292 
00293         if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
00294                 return False;
00295 
00296         /* 
00297          * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
00298          * the linked list.
00299          */
00300 
00301         if (lp_we_are_a_wins_server()) {
00302                 if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
00303                                                 WINS_SERVER_SUBNET, 
00304                                                 ipzero, ipzero, ipzero )) == NULL )
00305                         return False;
00306         }
00307 
00308         return True;
00309 }
00310 
00311 /*******************************************************************
00312 Function to tell us if we can use the unicast subnet.
00313 ******************************************************************/
00314 
00315 BOOL we_are_a_wins_client(void)
00316 {
00317         if (wins_srv_count() > 0) {
00318                 return True;
00319         }
00320 
00321         return False;
00322 }
00323 
00324 /*******************************************************************
00325 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
00326 ******************************************************************/
00327 
00328 struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
00329 {
00330         if(subrec == unicast_subnet)
00331                 return NULL;
00332         else if((subrec->next == NULL) && we_are_a_wins_client())
00333                 return unicast_subnet;
00334         else
00335                 return subrec->next;
00336 }
00337 
00338 /*******************************************************************
00339  Access function used by retransmit_or_expire_response_records() in
00340  nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
00341  Needed when we need to enumerate all the broadcast, unicast and
00342  WINS subnets.
00343 ******************************************************************/
00344 
00345 struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
00346 {
00347         if(subrec == unicast_subnet) {
00348                 if(wins_server_subnet)
00349                         return wins_server_subnet;
00350                 else
00351                         return NULL;
00352         }
00353 
00354         if(wins_server_subnet && subrec == wins_server_subnet)
00355                 return NULL;
00356 
00357         if((subrec->next == NULL) && we_are_a_wins_client())
00358                 return unicast_subnet;
00359         else
00360                 return subrec->next;
00361 }

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