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
->dgram_sock
!= -1) {
60 close(subrec
->dgram_sock
);
61 subrec
->dgram_sock
= -1;
63 if (subrec
->nmb_sock
!= -1) {
64 close(subrec
->nmb_sock
);
65 subrec
->nmb_sock
= -1;
68 DLIST_REMOVE(subnetlist
, subrec
);
71 /****************************************************************************
72 Create a subnet entry.
73 ****************************************************************************/
75 static struct subnet_record
*make_subnet(const char *name
, enum subnet_type type
,
76 struct in_addr myip
, struct in_addr bcast_ip
,
77 struct in_addr mask_ip
)
79 struct subnet_record
*subrec
= NULL
;
84 bool bind_bcast
= lp_nmbd_bind_explicit_broadcast();
86 /* Check if we are creating a non broadcast subnet - if so don't create
89 if (type
== NORMAL_SUBNET
) {
90 struct sockaddr_storage ss
;
91 struct sockaddr_storage ss_bcast
;
93 in_addr_to_sockaddr_storage(&ss
, myip
);
94 in_addr_to_sockaddr_storage(&ss_bcast
, bcast_ip
);
97 * Attempt to open the sockets on port 137/138 for this interface
99 * Fail the subnet creation if this fails.
102 nmb_sock
= open_socket_in(SOCK_DGRAM
, global_nmb_port
,
104 if (nmb_sock
== -1) {
105 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
106 DEBUGADD(0,(" Failed to open nmb socket on interface %s ",
108 DEBUGADD(0,("for port %d. ", global_nmb_port
));
109 DEBUGADD(0,("Error was %s\n", strerror(errno
)));
112 set_socket_options(nmb_sock
,"SO_BROADCAST");
113 set_blocking(nmb_sock
, false);
116 nmb_bcast
= open_socket_in(SOCK_DGRAM
, global_nmb_port
,
118 if (nmb_bcast
== -1) {
119 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
120 DEBUGADD(0,(" Failed to open nmb bcast socket on interface %s ",
121 inet_ntoa(bcast_ip
)));
122 DEBUGADD(0,("for port %d. ", global_nmb_port
));
123 DEBUGADD(0,("Error was %s\n", strerror(errno
)));
126 set_socket_options(nmb_bcast
, "SO_BROADCAST");
127 set_blocking(nmb_bcast
, false);
130 dgram_sock
= open_socket_in(SOCK_DGRAM
, DGRAM_PORT
,
132 if (dgram_sock
== -1) {
133 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
134 DEBUGADD(0,(" Failed to open dgram socket on interface %s ",
136 DEBUGADD(0,("for port %d. ", DGRAM_PORT
));
137 DEBUGADD(0,("Error was %s\n", strerror(errno
)));
140 set_socket_options(dgram_sock
, "SO_BROADCAST");
141 set_blocking(dgram_sock
, false);
144 dgram_bcast
= open_socket_in(SOCK_DGRAM
, DGRAM_PORT
,
146 if (dgram_bcast
== -1) {
147 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
148 DEBUGADD(0,(" Failed to open dgram bcast socket on interface %s ",
149 inet_ntoa(bcast_ip
)));
150 DEBUGADD(0,("for port %d. ", DGRAM_PORT
));
151 DEBUGADD(0,("Error was %s\n", strerror(errno
)));
154 set_socket_options(dgram_bcast
, "SO_BROADCAST");
155 set_blocking(dgram_bcast
, false);
159 subrec
= SMB_MALLOC_P(struct subnet_record
);
161 DEBUG(0,("make_subnet: malloc fail !\n"));
165 ZERO_STRUCTP(subrec
);
167 if((subrec
->subnet_name
= SMB_STRDUP(name
)) == NULL
) {
168 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
172 DEBUG(2, ("making subnet name:%s ", name
));
173 DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip
)));
174 DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip
)));
176 subrec
->namelist_changed
= False
;
177 subrec
->work_changed
= False
;
179 subrec
->bcast_ip
= bcast_ip
;
180 subrec
->mask_ip
= mask_ip
;
183 subrec
->nmb_sock
= nmb_sock
;
184 subrec
->nmb_bcast
= nmb_bcast
;
185 subrec
->dgram_sock
= dgram_sock
;
186 subrec
->dgram_bcast
= dgram_bcast
;
192 if (nmb_sock
!= -1) {
195 if (nmb_bcast
!= -1) {
198 if (dgram_sock
!= -1) {
201 if (dgram_bcast
!= -1) {
207 /****************************************************************************
208 Create a normal subnet
209 **************************************************************************/
211 struct subnet_record
*make_normal_subnet(const struct interface
*iface
)
214 struct subnet_record
*subrec
;
215 const struct in_addr
*pip
= &((const struct sockaddr_in
*)&iface
->ip
)->sin_addr
;
216 const struct in_addr
*pbcast
= &((const struct sockaddr_in
*)&iface
->bcast
)->sin_addr
;
217 const struct in_addr
*pnmask
= &((const struct sockaddr_in
*)&iface
->netmask
)->sin_addr
;
219 subrec
= make_subnet(inet_ntoa(*pip
), NORMAL_SUBNET
,
220 *pip
, *pbcast
, *pnmask
);
227 /****************************************************************************
228 Create subnet entries.
229 **************************************************************************/
231 bool create_subnets(void)
233 /* We only count IPv4 interfaces whilst we're waiting. */
236 struct in_addr unicast_ip
, ipzero
;
238 try_interfaces_again
:
240 /* Only count IPv4, non-loopback interfaces. */
241 if (iface_count_v4_nl() == 0) {
242 DEBUG(0,("create_subnets: No local IPv4 non-loopback interfaces !\n"));
243 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
246 /* We only count IPv4, non-loopback interfaces here. */
247 while (iface_count_v4_nl() == 0) {
248 void (*saved_handler
)(int);
251 * Whilst we're waiting for an interface, allow SIGTERM to
255 saved_handler
= CatchSignal(SIGTERM
, SIG_DFL
);
261 * We got an interface, restore our normal term handler.
264 CatchSignal(SIGTERM
, saved_handler
);
268 * Here we count v4 and v6 - we know there's at least one
269 * IPv4 interface and we filter on it below.
271 num_interfaces
= iface_count();
274 * Create subnets from all the local interfaces and thread them onto
278 for (i
= 0 ; i
< num_interfaces
; i
++) {
279 const struct interface
*iface
= get_interface(i
);
282 DEBUG(2,("create_subnets: can't get interface %d.\n", i
));
286 /* Ensure we're only dealing with IPv4 here. */
287 if (iface
->ip
.ss_family
!= AF_INET
) {
288 DEBUG(2,("create_subnets: "
289 "ignoring non IPv4 interface.\n"));
294 * We don't want to add a loopback interface, in case
295 * someone has added 127.0.0.1 for smbd, nmbd needs to
296 * ignore it here. JRA.
299 if (is_loopback_addr((const struct sockaddr
*)&iface
->ip
)) {
300 DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
304 if (!make_normal_subnet(iface
))
308 /* We must have at least one subnet. */
309 if (subnetlist
== NULL
) {
310 void (*saved_handler
)(int);
312 DEBUG(0,("create_subnets: Unable to create any subnet from "
313 "given interfaces. Is your interface line in "
314 "smb.conf correct ?\n"));
316 saved_handler
= CatchSignal(SIGTERM
, SIG_DFL
);
321 CatchSignal(SIGTERM
, saved_handler
);
322 goto try_interfaces_again
;
325 if (lp_we_are_a_wins_server()) {
326 /* Pick the first interface IPv4 address as the WINS server
328 const struct in_addr
*nip
= first_ipv4_iface();
336 /* note that we do not set the wins server IP here. We just
337 set it at zero and let the wins registration code cope
338 with getting the IPs right for each packet */
339 zero_ip_v4(&unicast_ip
);
343 * Create the unicast and remote broadcast subnets.
344 * Don't put these onto the linked list.
345 * The ip address of the unicast subnet is set to be
346 * the WINS server address, if it exists, or ipzero if not.
349 unicast_subnet
= make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET
,
350 unicast_ip
, unicast_ip
, unicast_ip
);
354 remote_broadcast_subnet
= make_subnet( "REMOTE_BROADCAST_SUBNET",
355 REMOTE_BROADCAST_SUBNET
,
356 ipzero
, ipzero
, ipzero
);
358 if((unicast_subnet
== NULL
) || (remote_broadcast_subnet
== NULL
))
362 * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
366 if (lp_we_are_a_wins_server()) {
367 if( (wins_server_subnet
= make_subnet( "WINS_SERVER_SUBNET",
369 ipzero
, ipzero
, ipzero
)) == NULL
)
376 /*******************************************************************
377 Function to tell us if we can use the unicast subnet.
378 ******************************************************************/
380 bool we_are_a_wins_client(void)
382 if (wins_srv_count() > 0) {
389 /*******************************************************************
390 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
391 ******************************************************************/
393 struct subnet_record
*get_next_subnet_maybe_unicast(struct subnet_record
*subrec
)
395 if(subrec
== unicast_subnet
)
397 else if((subrec
->next
== NULL
) && we_are_a_wins_client())
398 return unicast_subnet
;
403 /*******************************************************************
404 Access function used by retransmit_or_expire_response_records() in
405 nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
406 Needed when we need to enumerate all the broadcast, unicast and
408 ******************************************************************/
410 struct subnet_record
*get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record
*subrec
)
412 if(subrec
== unicast_subnet
) {
413 if(wins_server_subnet
)
414 return wins_server_subnet
;
419 if(wins_server_subnet
&& subrec
== wins_server_subnet
)
422 if((subrec
->next
== NULL
) && we_are_a_wins_client())
423 return unicast_subnet
;