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
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.
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.
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/>.
26 #include "nmbd/nmbd.h"
28 extern int global_nmb_port
;
30 /* This is the broadcast subnets database. */
31 struct subnet_record
*subnetlist
= NULL
;
33 /* Extra subnets - keep these separate so enumeration code doesn't
34 run onto it by mistake. */
36 struct subnet_record
*unicast_subnet
= NULL
;
37 struct subnet_record
*remote_broadcast_subnet
= NULL
;
38 struct subnet_record
*wins_server_subnet
= NULL
;
40 extern uint16 samba_nb_type
; /* Samba's NetBIOS name type. */
42 /****************************************************************************
43 Add a subnet into the list.
44 **************************************************************************/
46 static void add_subnet(struct subnet_record
*subrec
)
48 DLIST_ADD(subnetlist
, subrec
);
51 /****************************************************************************
52 stop listening on a subnet
53 we don't free the record as we don't have proper reference counting for it
54 yet and it may be in use by a response record
55 ****************************************************************************/
57 void close_subnet(struct subnet_record
*subrec
)
59 if (subrec
->nmb_sock
!= -1) {
60 close(subrec
->nmb_sock
);
61 subrec
->nmb_sock
= -1;
63 if (subrec
->nmb_bcast
!= -1) {
64 close(subrec
->nmb_bcast
);
65 subrec
->nmb_bcast
= -1;
67 if (subrec
->dgram_sock
!= -1) {
68 close(subrec
->dgram_sock
);
69 subrec
->dgram_sock
= -1;
71 if (subrec
->dgram_bcast
!= -1) {
72 close(subrec
->dgram_bcast
);
73 subrec
->dgram_bcast
= -1;
76 DLIST_REMOVE(subnetlist
, subrec
);
79 /****************************************************************************
80 Create a subnet entry.
81 ****************************************************************************/
83 static struct subnet_record
*make_subnet(const char *name
, enum subnet_type type
,
84 struct in_addr myip
, struct in_addr bcast_ip
,
85 struct in_addr mask_ip
)
87 struct subnet_record
*subrec
= NULL
;
92 bool bind_bcast
= lp_nmbd_bind_explicit_broadcast();
94 /* Check if we are creating a non broadcast subnet - if so don't create
97 if (type
== NORMAL_SUBNET
) {
98 struct sockaddr_storage ss
;
99 struct sockaddr_storage ss_bcast
;
101 in_addr_to_sockaddr_storage(&ss
, myip
);
102 in_addr_to_sockaddr_storage(&ss_bcast
, bcast_ip
);
105 * Attempt to open the sockets on port 137/138 for this interface
107 * Fail the subnet creation if this fails.
110 nmb_sock
= open_socket_in(SOCK_DGRAM
, global_nmb_port
,
112 if (nmb_sock
== -1) {
113 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
114 DEBUGADD(0,(" Failed to open nmb socket on interface %s ",
116 DEBUGADD(0,("for port %d. ", global_nmb_port
));
117 DEBUGADD(0,("Error was %s\n", strerror(errno
)));
120 set_socket_options(nmb_sock
,"SO_BROADCAST");
121 set_blocking(nmb_sock
, false);
124 nmb_bcast
= open_socket_in(SOCK_DGRAM
, global_nmb_port
,
126 if (nmb_bcast
== -1) {
127 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
128 DEBUGADD(0,(" Failed to open nmb bcast socket on interface %s ",
129 inet_ntoa(bcast_ip
)));
130 DEBUGADD(0,("for port %d. ", global_nmb_port
));
131 DEBUGADD(0,("Error was %s\n", strerror(errno
)));
134 set_socket_options(nmb_bcast
, "SO_BROADCAST");
135 set_blocking(nmb_bcast
, false);
138 dgram_sock
= open_socket_in(SOCK_DGRAM
, DGRAM_PORT
,
140 if (dgram_sock
== -1) {
141 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
142 DEBUGADD(0,(" Failed to open dgram socket on interface %s ",
144 DEBUGADD(0,("for port %d. ", DGRAM_PORT
));
145 DEBUGADD(0,("Error was %s\n", strerror(errno
)));
148 set_socket_options(dgram_sock
, "SO_BROADCAST");
149 set_blocking(dgram_sock
, false);
152 dgram_bcast
= open_socket_in(SOCK_DGRAM
, DGRAM_PORT
,
154 if (dgram_bcast
== -1) {
155 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
156 DEBUGADD(0,(" Failed to open dgram bcast socket on interface %s ",
157 inet_ntoa(bcast_ip
)));
158 DEBUGADD(0,("for port %d. ", DGRAM_PORT
));
159 DEBUGADD(0,("Error was %s\n", strerror(errno
)));
162 set_socket_options(dgram_bcast
, "SO_BROADCAST");
163 set_blocking(dgram_bcast
, false);
167 subrec
= SMB_MALLOC_P(struct subnet_record
);
169 DEBUG(0,("make_subnet: malloc fail !\n"));
173 ZERO_STRUCTP(subrec
);
175 if((subrec
->subnet_name
= SMB_STRDUP(name
)) == NULL
) {
176 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
180 DEBUG(2, ("making subnet name:%s ", name
));
181 DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip
)));
182 DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip
)));
184 subrec
->namelist_changed
= False
;
185 subrec
->work_changed
= False
;
187 subrec
->bcast_ip
= bcast_ip
;
188 subrec
->mask_ip
= mask_ip
;
191 subrec
->nmb_sock
= nmb_sock
;
192 subrec
->nmb_bcast
= nmb_bcast
;
193 subrec
->dgram_sock
= dgram_sock
;
194 subrec
->dgram_bcast
= dgram_bcast
;
200 if (nmb_sock
!= -1) {
203 if (nmb_bcast
!= -1) {
206 if (dgram_sock
!= -1) {
209 if (dgram_bcast
!= -1) {
215 /****************************************************************************
216 Create a normal subnet
217 **************************************************************************/
219 struct subnet_record
*make_normal_subnet(const struct interface
*iface
)
222 struct subnet_record
*subrec
;
223 const struct in_addr
*pip
= &((const struct sockaddr_in
*)&iface
->ip
)->sin_addr
;
224 const struct in_addr
*pbcast
= &((const struct sockaddr_in
*)&iface
->bcast
)->sin_addr
;
225 const struct in_addr
*pnmask
= &((const struct sockaddr_in
*)&iface
->netmask
)->sin_addr
;
227 subrec
= make_subnet(inet_ntoa(*pip
), NORMAL_SUBNET
,
228 *pip
, *pbcast
, *pnmask
);
235 /****************************************************************************
236 Create subnet entries.
237 **************************************************************************/
239 bool create_subnets(void)
241 /* We only count IPv4 interfaces whilst we're waiting. */
244 struct in_addr unicast_ip
, ipzero
;
246 try_interfaces_again
:
248 /* Only count IPv4, non-loopback interfaces. */
249 if (iface_count_v4_nl() == 0) {
250 DEBUG(0,("create_subnets: No local IPv4 non-loopback interfaces !\n"));
251 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
254 /* We only count IPv4, non-loopback interfaces here. */
255 while (iface_count_v4_nl() == 0) {
256 void (*saved_handler
)(int);
259 * Whilst we're waiting for an interface, allow SIGTERM to
263 saved_handler
= CatchSignal(SIGTERM
, SIG_DFL
);
269 * We got an interface, restore our normal term handler.
272 CatchSignal(SIGTERM
, saved_handler
);
276 * Here we count v4 and v6 - we know there's at least one
277 * IPv4 interface and we filter on it below.
279 num_interfaces
= iface_count();
282 * Create subnets from all the local interfaces and thread them onto
286 for (i
= 0 ; i
< num_interfaces
; i
++) {
287 const struct interface
*iface
= get_interface(i
);
290 DEBUG(2,("create_subnets: can't get interface %d.\n", i
));
294 /* Ensure we're only dealing with IPv4 here. */
295 if (iface
->ip
.ss_family
!= AF_INET
) {
296 DEBUG(2,("create_subnets: "
297 "ignoring non IPv4 interface.\n"));
302 * We don't want to add a loopback interface, in case
303 * someone has added 127.0.0.1 for smbd, nmbd needs to
304 * ignore it here. JRA.
307 if (is_loopback_addr((struct sockaddr
*)&iface
->ip
)) {
308 DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
312 if (!make_normal_subnet(iface
))
316 /* We must have at least one subnet. */
317 if (subnetlist
== NULL
) {
318 void (*saved_handler
)(int);
320 DEBUG(0,("create_subnets: Unable to create any subnet from "
321 "given interfaces. Is your interface line in "
322 "smb.conf correct ?\n"));
324 saved_handler
= CatchSignal(SIGTERM
, SIG_DFL
);
329 CatchSignal(SIGTERM
, saved_handler
);
330 goto try_interfaces_again
;
333 if (lp_we_are_a_wins_server()) {
334 /* Pick the first interface IPv4 address as the WINS server
336 const struct in_addr
*nip
= first_ipv4_iface();
344 /* note that we do not set the wins server IP here. We just
345 set it at zero and let the wins registration code cope
346 with getting the IPs right for each packet */
347 zero_ip_v4(&unicast_ip
);
351 * Create the unicast and remote broadcast subnets.
352 * Don't put these onto the linked list.
353 * The ip address of the unicast subnet is set to be
354 * the WINS server address, if it exists, or ipzero if not.
357 unicast_subnet
= make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET
,
358 unicast_ip
, unicast_ip
, unicast_ip
);
362 remote_broadcast_subnet
= make_subnet( "REMOTE_BROADCAST_SUBNET",
363 REMOTE_BROADCAST_SUBNET
,
364 ipzero
, ipzero
, ipzero
);
366 if((unicast_subnet
== NULL
) || (remote_broadcast_subnet
== NULL
))
370 * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
374 if (lp_we_are_a_wins_server()) {
375 if( (wins_server_subnet
= make_subnet( "WINS_SERVER_SUBNET",
377 ipzero
, ipzero
, ipzero
)) == NULL
)
384 /*******************************************************************
385 Function to tell us if we can use the unicast subnet.
386 ******************************************************************/
388 bool we_are_a_wins_client(void)
390 if (wins_srv_count() > 0) {
397 /*******************************************************************
398 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
399 ******************************************************************/
401 struct subnet_record
*get_next_subnet_maybe_unicast(struct subnet_record
*subrec
)
403 if(subrec
== unicast_subnet
)
405 else if((subrec
->next
== NULL
) && we_are_a_wins_client())
406 return unicast_subnet
;
411 /*******************************************************************
412 Access function used by retransmit_or_expire_response_records() in
413 nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
414 Needed when we need to enumerate all the broadcast, unicast and
416 ******************************************************************/
418 struct subnet_record
*get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record
*subrec
)
420 if(subrec
== unicast_subnet
) {
421 if(wins_server_subnet
)
422 return wins_server_subnet
;
427 if(wins_server_subnet
&& subrec
== wins_server_subnet
)
430 if((subrec
->next
== NULL
) && we_are_a_wins_client())
431 return unicast_subnet
;