| 1 | /* 
 | 
|---|
| 2 |    Unix SMB/CIFS implementation.
 | 
|---|
| 3 |    NBT netbios routines and daemon - version 2
 | 
|---|
| 4 |    Copyright (C) Andrew Tridgell 1994-1998
 | 
|---|
| 5 |    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
 | 
|---|
| 6 |    Copyright (C) Jeremy Allison 1994-1998
 | 
|---|
| 7 |    
 | 
|---|
| 8 |    This program is free software; you can redistribute it and/or modify
 | 
|---|
| 9 |    it under the terms of the GNU General Public License as published by
 | 
|---|
| 10 |    the Free Software Foundation; either version 3 of the License, or
 | 
|---|
| 11 |    (at your option) any later version.
 | 
|---|
| 12 |    
 | 
|---|
| 13 |    This program is distributed in the hope that it will be useful,
 | 
|---|
| 14 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 15 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 16 |    GNU General Public License for more details.
 | 
|---|
| 17 |    
 | 
|---|
| 18 |    You should have received a copy of the GNU General Public License
 | 
|---|
| 19 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
|---|
| 20 |    
 | 
|---|
| 21 |    Revision History:
 | 
|---|
| 22 | 
 | 
|---|
| 23 | */
 | 
|---|
| 24 | 
 | 
|---|
| 25 | #include "includes.h"
 | 
|---|
| 26 | 
 | 
|---|
| 27 | extern int global_nmb_port;
 | 
|---|
| 28 | 
 | 
|---|
| 29 | /* This is the broadcast subnets database. */
 | 
|---|
| 30 | struct subnet_record *subnetlist = NULL;
 | 
|---|
| 31 | 
 | 
|---|
| 32 | /* Extra subnets - keep these separate so enumeration code doesn't
 | 
|---|
| 33 |    run onto it by mistake. */
 | 
|---|
| 34 | 
 | 
|---|
| 35 | struct subnet_record *unicast_subnet = NULL;
 | 
|---|
| 36 | struct subnet_record *remote_broadcast_subnet = NULL;
 | 
|---|
| 37 | struct subnet_record *wins_server_subnet = NULL;
 | 
|---|
| 38 | 
 | 
|---|
| 39 | extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
 | 
|---|
| 40 | 
 | 
|---|
| 41 | /****************************************************************************
 | 
|---|
| 42 |   Add a subnet into the list.
 | 
|---|
| 43 |   **************************************************************************/
 | 
|---|
| 44 | 
 | 
|---|
| 45 | static void add_subnet(struct subnet_record *subrec)
 | 
|---|
| 46 | {
 | 
|---|
| 47 |         DLIST_ADD(subnetlist, subrec);
 | 
|---|
| 48 | }
 | 
|---|
| 49 | 
 | 
|---|
| 50 | /****************************************************************************
 | 
|---|
| 51 | stop listening on a subnet
 | 
|---|
| 52 | we don't free the record as we don't have proper reference counting for it
 | 
|---|
| 53 | yet and it may be in use by a response record
 | 
|---|
| 54 |   ****************************************************************************/
 | 
|---|
| 55 | 
 | 
|---|
| 56 | void close_subnet(struct subnet_record *subrec)
 | 
|---|
| 57 | {
 | 
|---|
| 58 |         if (subrec->nmb_sock != -1) {
 | 
|---|
| 59 |                 close(subrec->nmb_sock);
 | 
|---|
| 60 |                 subrec->nmb_sock = -1;
 | 
|---|
| 61 |         }
 | 
|---|
| 62 |         if (subrec->nmb_bcast != -1) {
 | 
|---|
| 63 |                 close(subrec->nmb_bcast);
 | 
|---|
| 64 |                 subrec->nmb_bcast = -1;
 | 
|---|
| 65 |         }
 | 
|---|
| 66 |         if (subrec->dgram_sock != -1) {
 | 
|---|
| 67 |                 close(subrec->dgram_sock);
 | 
|---|
| 68 |                 subrec->dgram_sock = -1;
 | 
|---|
| 69 |         }
 | 
|---|
| 70 |         if (subrec->dgram_bcast != -1) {
 | 
|---|
| 71 |                 close(subrec->dgram_bcast);
 | 
|---|
| 72 |                 subrec->dgram_bcast = -1;
 | 
|---|
| 73 |         }
 | 
|---|
| 74 | 
 | 
|---|
| 75 |         DLIST_REMOVE(subnetlist, subrec);
 | 
|---|
| 76 | }
 | 
|---|
| 77 | 
 | 
|---|
| 78 | /****************************************************************************
 | 
|---|
| 79 |   Create a subnet entry.
 | 
|---|
| 80 |   ****************************************************************************/
 | 
|---|
| 81 | 
 | 
|---|
| 82 | static struct subnet_record *make_subnet(const char *name, enum subnet_type type,
 | 
|---|
| 83 |                                          struct in_addr myip, struct in_addr bcast_ip, 
 | 
|---|
| 84 |                                          struct in_addr mask_ip)
 | 
|---|
| 85 | {
 | 
|---|
| 86 |         struct subnet_record *subrec = NULL;
 | 
|---|
| 87 |         int nmb_sock = -1;
 | 
|---|
| 88 |         int dgram_sock = -1;
 | 
|---|
| 89 |         int nmb_bcast = -1;
 | 
|---|
| 90 |         int dgram_bcast = -1;
 | 
|---|
| 91 |         bool bind_bcast = lp_nmbd_bind_explicit_broadcast();
 | 
|---|
| 92 | 
 | 
|---|
| 93 |         /* Check if we are creating a non broadcast subnet - if so don't create
 | 
|---|
| 94 |                 sockets.  */
 | 
|---|
| 95 | 
 | 
|---|
| 96 |         if (type == NORMAL_SUBNET) {
 | 
|---|
| 97 |                 struct sockaddr_storage ss;
 | 
|---|
| 98 |                 struct sockaddr_storage ss_bcast;
 | 
|---|
| 99 | 
 | 
|---|
| 100 |                 in_addr_to_sockaddr_storage(&ss, myip);
 | 
|---|
| 101 |                 in_addr_to_sockaddr_storage(&ss_bcast, bcast_ip);
 | 
|---|
| 102 | 
 | 
|---|
| 103 |                 /*
 | 
|---|
| 104 |                  * Attempt to open the sockets on port 137/138 for this interface
 | 
|---|
| 105 |                  * and bind them.
 | 
|---|
| 106 |                  * Fail the subnet creation if this fails.
 | 
|---|
| 107 |                  */
 | 
|---|
| 108 | 
 | 
|---|
| 109 |                 nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,
 | 
|---|
| 110 |                                           0, &ss, true);
 | 
|---|
| 111 |                 if (nmb_sock == -1) {
 | 
|---|
| 112 |                         DEBUG(0,   ("nmbd_subnetdb:make_subnet()\n"));
 | 
|---|
| 113 |                         DEBUGADD(0,("  Failed to open nmb socket on interface %s ",
 | 
|---|
| 114 |                                     inet_ntoa(myip)));
 | 
|---|
| 115 |                         DEBUGADD(0,("for port %d.  ", global_nmb_port));
 | 
|---|
| 116 |                         DEBUGADD(0,("Error was %s\n", strerror(errno)));
 | 
|---|
| 117 |                         goto failed;
 | 
|---|
| 118 |                 }
 | 
|---|
| 119 |                 set_socket_options(nmb_sock,"SO_BROADCAST");
 | 
|---|
| 120 |                 set_blocking(nmb_sock, false);
 | 
|---|
| 121 | 
 | 
|---|
| 122 |                 if (bind_bcast) {
 | 
|---|
| 123 |                         nmb_bcast = open_socket_in(SOCK_DGRAM, global_nmb_port,
 | 
|---|
| 124 |                                                    0, &ss_bcast, true);
 | 
|---|
| 125 |                         if (nmb_bcast == -1) {
 | 
|---|
| 126 |                                 DEBUG(0,   ("nmbd_subnetdb:make_subnet()\n"));
 | 
|---|
| 127 |                                 DEBUGADD(0,("  Failed to open nmb bcast socket on interface %s ",
 | 
|---|
| 128 |                                             inet_ntoa(bcast_ip)));
 | 
|---|
| 129 |                                 DEBUGADD(0,("for port %d.  ", global_nmb_port));
 | 
|---|
| 130 |                                 DEBUGADD(0,("Error was %s\n", strerror(errno)));
 | 
|---|
| 131 |                                 goto failed;
 | 
|---|
| 132 |                         }
 | 
|---|
| 133 |                         set_socket_options(nmb_bcast, "SO_BROADCAST");
 | 
|---|
| 134 |                         set_blocking(nmb_bcast, false);
 | 
|---|
| 135 |                 }
 | 
|---|
| 136 | 
 | 
|---|
| 137 |                 dgram_sock = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
 | 
|---|
| 138 |                                             3, &ss, true);
 | 
|---|
| 139 |                 if (dgram_sock == -1) {
 | 
|---|
| 140 |                         DEBUG(0,   ("nmbd_subnetdb:make_subnet()\n"));
 | 
|---|
| 141 |                         DEBUGADD(0,("  Failed to open dgram socket on interface %s ",
 | 
|---|
| 142 |                                     inet_ntoa(myip)));
 | 
|---|
| 143 |                         DEBUGADD(0,("for port %d.  ", DGRAM_PORT));
 | 
|---|
| 144 |                         DEBUGADD(0,("Error was %s\n", strerror(errno)));
 | 
|---|
| 145 |                         goto failed;
 | 
|---|
| 146 |                 }
 | 
|---|
| 147 |                 set_socket_options(dgram_sock, "SO_BROADCAST");
 | 
|---|
| 148 |                 set_blocking(dgram_sock, false);
 | 
|---|
| 149 | 
 | 
|---|
| 150 |                 if (bind_bcast) {
 | 
|---|
| 151 |                         dgram_bcast = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
 | 
|---|
| 152 |                                                      3, &ss_bcast, true);
 | 
|---|
| 153 |                         if (dgram_bcast == -1) {
 | 
|---|
| 154 |                                 DEBUG(0,   ("nmbd_subnetdb:make_subnet()\n"));
 | 
|---|
| 155 |                                 DEBUGADD(0,("  Failed to open dgram bcast socket on interface %s ",
 | 
|---|
| 156 |                                             inet_ntoa(bcast_ip)));
 | 
|---|
| 157 |                                 DEBUGADD(0,("for port %d.  ", DGRAM_PORT));
 | 
|---|
| 158 |                                 DEBUGADD(0,("Error was %s\n", strerror(errno)));
 | 
|---|
| 159 |                                 goto failed;
 | 
|---|
| 160 |                         }
 | 
|---|
| 161 |                         set_socket_options(dgram_bcast, "SO_BROADCAST");
 | 
|---|
| 162 |                         set_blocking(dgram_bcast, false);
 | 
|---|
| 163 |                 }
 | 
|---|
| 164 |         }
 | 
|---|
| 165 | 
 | 
|---|
| 166 |         subrec = SMB_MALLOC_P(struct subnet_record);
 | 
|---|
| 167 |         if (!subrec) {
 | 
|---|
| 168 |                 DEBUG(0,("make_subnet: malloc fail !\n"));
 | 
|---|
| 169 |                 goto failed;
 | 
|---|
| 170 |         }
 | 
|---|
| 171 |   
 | 
|---|
| 172 |         ZERO_STRUCTP(subrec);
 | 
|---|
| 173 | 
 | 
|---|
| 174 |         if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
 | 
|---|
| 175 |                 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
 | 
|---|
| 176 |                 goto failed;
 | 
|---|
| 177 |         }
 | 
|---|
| 178 | 
 | 
|---|
| 179 |         DEBUG(2, ("making subnet name:%s ", name ));
 | 
|---|
| 180 |         DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
 | 
|---|
| 181 |         DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
 | 
|---|
| 182 |  
 | 
|---|
| 183 |         subrec->namelist_changed = False;
 | 
|---|
| 184 |         subrec->work_changed = False;
 | 
|---|
| 185 |  
 | 
|---|
| 186 |         subrec->bcast_ip = bcast_ip;
 | 
|---|
| 187 |         subrec->mask_ip  = mask_ip;
 | 
|---|
| 188 |         subrec->myip = myip;
 | 
|---|
| 189 |         subrec->type = type;
 | 
|---|
| 190 |         subrec->nmb_sock = nmb_sock;
 | 
|---|
| 191 |         subrec->nmb_bcast = nmb_bcast;
 | 
|---|
| 192 |         subrec->dgram_sock = dgram_sock;
 | 
|---|
| 193 |         subrec->dgram_bcast = dgram_bcast;
 | 
|---|
| 194 | 
 | 
|---|
| 195 |         return subrec;
 | 
|---|
| 196 | 
 | 
|---|
| 197 | failed:
 | 
|---|
| 198 |         SAFE_FREE(subrec);
 | 
|---|
| 199 |         if (nmb_sock != -1) {
 | 
|---|
| 200 |                 close(nmb_sock);
 | 
|---|
| 201 |         }
 | 
|---|
| 202 |         if (nmb_bcast != -1) {
 | 
|---|
| 203 |                 close(nmb_bcast);
 | 
|---|
| 204 |         }
 | 
|---|
| 205 |         if (dgram_sock != -1) {
 | 
|---|
| 206 |                 close(dgram_sock);
 | 
|---|
| 207 |         }
 | 
|---|
| 208 |         if (dgram_bcast != -1) {
 | 
|---|
| 209 |                 close(dgram_bcast);
 | 
|---|
| 210 |         }
 | 
|---|
| 211 |         return NULL;
 | 
|---|
| 212 | }
 | 
|---|
| 213 | 
 | 
|---|
| 214 | /****************************************************************************
 | 
|---|
| 215 |   Create a normal subnet
 | 
|---|
| 216 | **************************************************************************/
 | 
|---|
| 217 | 
 | 
|---|
| 218 | struct subnet_record *make_normal_subnet(const struct interface *iface)
 | 
|---|
| 219 | {
 | 
|---|
| 220 | 
 | 
|---|
| 221 |         struct subnet_record *subrec;
 | 
|---|
| 222 |         const struct in_addr *pip = &((const struct sockaddr_in *)&iface->ip)->sin_addr;
 | 
|---|
| 223 |         const struct in_addr *pbcast = &((const struct sockaddr_in *)&iface->bcast)->sin_addr;
 | 
|---|
| 224 |         const struct in_addr *pnmask = &((const struct sockaddr_in *)&iface->netmask)->sin_addr;
 | 
|---|
| 225 | 
 | 
|---|
| 226 |         subrec = make_subnet(inet_ntoa(*pip), NORMAL_SUBNET,
 | 
|---|
| 227 |                              *pip, *pbcast, *pnmask);
 | 
|---|
| 228 |         if (subrec) {
 | 
|---|
| 229 |                 add_subnet(subrec);
 | 
|---|
| 230 |         }
 | 
|---|
| 231 |         return subrec;
 | 
|---|
| 232 | }
 | 
|---|
| 233 | 
 | 
|---|
| 234 | /****************************************************************************
 | 
|---|
| 235 |   Create subnet entries.
 | 
|---|
| 236 | **************************************************************************/
 | 
|---|
| 237 | 
 | 
|---|
| 238 | bool create_subnets(void)
 | 
|---|
| 239 | {
 | 
|---|
| 240 |         /* We only count IPv4 interfaces whilst we're waiting. */
 | 
|---|
| 241 |         int num_interfaces;
 | 
|---|
| 242 |         int i;
 | 
|---|
| 243 |         struct in_addr unicast_ip, ipzero;
 | 
|---|
| 244 | 
 | 
|---|
| 245 |   try_interfaces_again:
 | 
|---|
| 246 | 
 | 
|---|
| 247 |         /* Only count IPv4, non-loopback interfaces. */
 | 
|---|
| 248 |         if (iface_count_v4_nl() == 0) {
 | 
|---|
| 249 |                 DEBUG(0,("create_subnets: No local IPv4 non-loopback interfaces !\n"));
 | 
|---|
| 250 |                 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
 | 
|---|
| 251 |         }
 | 
|---|
| 252 | 
 | 
|---|
| 253 |         /* We only count IPv4, non-loopback interfaces here. */
 | 
|---|
| 254 |         while (iface_count_v4_nl() == 0) {
 | 
|---|
| 255 |                 void (*saved_handler)(int);
 | 
|---|
| 256 | 
 | 
|---|
| 257 |                 /*
 | 
|---|
| 258 |                  * Whilst we're waiting for an interface, allow SIGTERM to
 | 
|---|
| 259 |                  * cause us to exit.
 | 
|---|
| 260 |                  */
 | 
|---|
| 261 | 
 | 
|---|
| 262 |                 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
 | 
|---|
| 263 | 
 | 
|---|
| 264 |                 sleep(5);
 | 
|---|
| 265 |                 load_interfaces();
 | 
|---|
| 266 | 
 | 
|---|
| 267 |                 /*
 | 
|---|
| 268 |                  * We got an interface, restore our normal term handler.
 | 
|---|
| 269 |                  */
 | 
|---|
| 270 | 
 | 
|---|
| 271 |                 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
 | 
|---|
| 272 |         }
 | 
|---|
| 273 | 
 | 
|---|
| 274 |         /*
 | 
|---|
| 275 |          * Here we count v4 and v6 - we know there's at least one
 | 
|---|
| 276 |          * IPv4 interface and we filter on it below.
 | 
|---|
| 277 |          */
 | 
|---|
| 278 |         num_interfaces = iface_count();
 | 
|---|
| 279 | 
 | 
|---|
| 280 |         /*
 | 
|---|
| 281 |          * Create subnets from all the local interfaces and thread them onto
 | 
|---|
| 282 |          * the linked list.
 | 
|---|
| 283 |          */
 | 
|---|
| 284 | 
 | 
|---|
| 285 |         for (i = 0 ; i < num_interfaces; i++) {
 | 
|---|
| 286 |                 const struct interface *iface = get_interface(i);
 | 
|---|
| 287 | 
 | 
|---|
| 288 |                 if (!iface) {
 | 
|---|
| 289 |                         DEBUG(2,("create_subnets: can't get interface %d.\n", i ));
 | 
|---|
| 290 |                         continue;
 | 
|---|
| 291 |                 }
 | 
|---|
| 292 | 
 | 
|---|
| 293 |                 /* Ensure we're only dealing with IPv4 here. */
 | 
|---|
| 294 |                 if (iface->ip.ss_family != AF_INET) {
 | 
|---|
| 295 |                         DEBUG(2,("create_subnets: "
 | 
|---|
| 296 |                                 "ignoring non IPv4 interface.\n"));
 | 
|---|
| 297 |                         continue;
 | 
|---|
| 298 |                 }
 | 
|---|
| 299 | 
 | 
|---|
| 300 |                 /*
 | 
|---|
| 301 |                  * We don't want to add a loopback interface, in case
 | 
|---|
| 302 |                  * someone has added 127.0.0.1 for smbd, nmbd needs to
 | 
|---|
| 303 |                  * ignore it here. JRA.
 | 
|---|
| 304 |                  */
 | 
|---|
| 305 | 
 | 
|---|
| 306 |                 if (is_loopback_addr((struct sockaddr *)&iface->ip)) {
 | 
|---|
| 307 |                         DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
 | 
|---|
| 308 |                         continue;
 | 
|---|
| 309 |                 }
 | 
|---|
| 310 | 
 | 
|---|
| 311 |                 if (!make_normal_subnet(iface))
 | 
|---|
| 312 |                         return False;
 | 
|---|
| 313 |         }
 | 
|---|
| 314 | 
 | 
|---|
| 315 |         /* We must have at least one subnet. */
 | 
|---|
| 316 |         if (subnetlist == NULL) {
 | 
|---|
| 317 |                 void (*saved_handler)(int);
 | 
|---|
| 318 | 
 | 
|---|
| 319 |                 DEBUG(0,("create_subnets: Unable to create any subnet from "
 | 
|---|
| 320 |                                 "given interfaces. Is your interface line in "
 | 
|---|
| 321 |                                 "smb.conf correct ?\n"));
 | 
|---|
| 322 | 
 | 
|---|
| 323 |                 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
 | 
|---|
| 324 | 
 | 
|---|
| 325 |                 sleep(5);
 | 
|---|
| 326 |                 load_interfaces();
 | 
|---|
| 327 | 
 | 
|---|
| 328 |                 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
 | 
|---|
| 329 |                 goto try_interfaces_again;
 | 
|---|
| 330 |         }
 | 
|---|
| 331 | 
 | 
|---|
| 332 |         if (lp_we_are_a_wins_server()) {
 | 
|---|
| 333 |                 /* Pick the first interface IPv4 address as the WINS server
 | 
|---|
| 334 |                  * ip. */
 | 
|---|
| 335 |                 const struct in_addr *nip = first_ipv4_iface();
 | 
|---|
| 336 | 
 | 
|---|
| 337 |                 if (!nip) {
 | 
|---|
| 338 |                         return False;
 | 
|---|
| 339 |                 }
 | 
|---|
| 340 | 
 | 
|---|
| 341 |                 unicast_ip = *nip;
 | 
|---|
| 342 |         } else {
 | 
|---|
| 343 |                 /* note that we do not set the wins server IP here. We just
 | 
|---|
| 344 |                         set it at zero and let the wins registration code cope
 | 
|---|
| 345 |                         with getting the IPs right for each packet */
 | 
|---|
| 346 |                 zero_ip_v4(&unicast_ip);
 | 
|---|
| 347 |         }
 | 
|---|
| 348 | 
 | 
|---|
| 349 |         /*
 | 
|---|
| 350 |          * Create the unicast and remote broadcast subnets.
 | 
|---|
| 351 |          * Don't put these onto the linked list.
 | 
|---|
| 352 |          * The ip address of the unicast subnet is set to be
 | 
|---|
| 353 |          * the WINS server address, if it exists, or ipzero if not.
 | 
|---|
| 354 |          */
 | 
|---|
| 355 | 
 | 
|---|
| 356 |         unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, 
 | 
|---|
| 357 |                                 unicast_ip, unicast_ip, unicast_ip);
 | 
|---|
| 358 | 
 | 
|---|
| 359 |         zero_ip_v4(&ipzero);
 | 
|---|
| 360 | 
 | 
|---|
| 361 |         remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
 | 
|---|
| 362 |                                 REMOTE_BROADCAST_SUBNET,
 | 
|---|
| 363 |                                 ipzero, ipzero, ipzero);
 | 
|---|
| 364 | 
 | 
|---|
| 365 |         if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
 | 
|---|
| 366 |                 return False;
 | 
|---|
| 367 | 
 | 
|---|
| 368 |         /* 
 | 
|---|
| 369 |          * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
 | 
|---|
| 370 |          * the linked list.
 | 
|---|
| 371 |          */
 | 
|---|
| 372 | 
 | 
|---|
| 373 |         if (lp_we_are_a_wins_server()) {
 | 
|---|
| 374 |                 if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
 | 
|---|
| 375 |                                                 WINS_SERVER_SUBNET, 
 | 
|---|
| 376 |                                                 ipzero, ipzero, ipzero )) == NULL )
 | 
|---|
| 377 |                         return False;
 | 
|---|
| 378 |         }
 | 
|---|
| 379 | 
 | 
|---|
| 380 |         return True;
 | 
|---|
| 381 | }
 | 
|---|
| 382 | 
 | 
|---|
| 383 | /*******************************************************************
 | 
|---|
| 384 | Function to tell us if we can use the unicast subnet.
 | 
|---|
| 385 | ******************************************************************/
 | 
|---|
| 386 | 
 | 
|---|
| 387 | bool we_are_a_wins_client(void)
 | 
|---|
| 388 | {
 | 
|---|
| 389 |         if (wins_srv_count() > 0) {
 | 
|---|
| 390 |                 return True;
 | 
|---|
| 391 |         }
 | 
|---|
| 392 | 
 | 
|---|
| 393 |         return False;
 | 
|---|
| 394 | }
 | 
|---|
| 395 | 
 | 
|---|
| 396 | /*******************************************************************
 | 
|---|
| 397 | Access function used by NEXT_SUBNET_INCLUDING_UNICAST
 | 
|---|
| 398 | ******************************************************************/
 | 
|---|
| 399 | 
 | 
|---|
| 400 | struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
 | 
|---|
| 401 | {
 | 
|---|
| 402 |         if(subrec == unicast_subnet)
 | 
|---|
| 403 |                 return NULL;
 | 
|---|
| 404 |         else if((subrec->next == NULL) && we_are_a_wins_client())
 | 
|---|
| 405 |                 return unicast_subnet;
 | 
|---|
| 406 |         else
 | 
|---|
| 407 |                 return subrec->next;
 | 
|---|
| 408 | }
 | 
|---|
| 409 | 
 | 
|---|
| 410 | /*******************************************************************
 | 
|---|
| 411 |  Access function used by retransmit_or_expire_response_records() in
 | 
|---|
| 412 |  nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
 | 
|---|
| 413 |  Needed when we need to enumerate all the broadcast, unicast and
 | 
|---|
| 414 |  WINS subnets.
 | 
|---|
| 415 | ******************************************************************/
 | 
|---|
| 416 | 
 | 
|---|
| 417 | struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
 | 
|---|
| 418 | {
 | 
|---|
| 419 |         if(subrec == unicast_subnet) {
 | 
|---|
| 420 |                 if(wins_server_subnet)
 | 
|---|
| 421 |                         return wins_server_subnet;
 | 
|---|
| 422 |                 else
 | 
|---|
| 423 |                         return NULL;
 | 
|---|
| 424 |         }
 | 
|---|
| 425 | 
 | 
|---|
| 426 |         if(wins_server_subnet && subrec == wins_server_subnet)
 | 
|---|
| 427 |                 return NULL;
 | 
|---|
| 428 | 
 | 
|---|
| 429 |         if((subrec->next == NULL) && we_are_a_wins_client())
 | 
|---|
| 430 |                 return unicast_subnet;
 | 
|---|
| 431 |         else
 | 
|---|
| 432 |                 return subrec->next;
 | 
|---|
| 433 | }
 | 
|---|