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/>.
27 extern int global_nmb_port
;
29 /* This is the broadcast subnets database. */
30 struct subnet_record
*subnetlist
= NULL
;
32 /* Extra subnets - keep these separate so enumeration code doesn't
33 run onto it by mistake. */
35 struct subnet_record
*unicast_subnet
= NULL
;
36 struct subnet_record
*remote_broadcast_subnet
= NULL
;
37 struct subnet_record
*wins_server_subnet
= NULL
;
39 extern uint16 samba_nb_type
; /* Samba's NetBIOS name type. */
41 /****************************************************************************
42 Add a subnet into the list.
43 **************************************************************************/
45 static void add_subnet(struct subnet_record
*subrec
)
47 DLIST_ADD(subnetlist
, subrec
);
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 ****************************************************************************/
56 void close_subnet(struct subnet_record
*subrec
)
58 if (subrec
->dgram_sock
!= -1) {
59 close(subrec
->dgram_sock
);
60 subrec
->dgram_sock
= -1;
62 if (subrec
->nmb_sock
!= -1) {
63 close(subrec
->nmb_sock
);
64 subrec
->nmb_sock
= -1;
67 DLIST_REMOVE(subnetlist
, subrec
);
70 /****************************************************************************
71 Create a subnet entry.
72 ****************************************************************************/
74 static struct subnet_record
*make_subnet(const char *name
, enum subnet_type type
,
75 struct in_addr myip
, struct in_addr bcast_ip
,
76 struct in_addr mask_ip
)
78 struct subnet_record
*subrec
= NULL
;
79 int nmb_sock
, dgram_sock
;
81 /* Check if we are creating a non broadcast subnet - if so don't create
84 if(type
!= NORMAL_SUBNET
) {
88 struct sockaddr_storage ss
;
90 in_addr_to_sockaddr_storage(&ss
, myip
);
93 * Attempt to open the sockets on port 137/138 for this interface
95 * Fail the subnet creation if this fails.
98 if((nmb_sock
= open_socket_in(SOCK_DGRAM
, global_nmb_port
,0, &ss
,true)) == -1) {
100 Debug1( "nmbd_subnetdb:make_subnet()\n" );
101 Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip
) );
102 Debug1( "for port %d. ", global_nmb_port
);
103 Debug1( "Error was %s\n", strerror(errno
) );
108 if((dgram_sock
= open_socket_in(SOCK_DGRAM
,DGRAM_PORT
,3, &ss
, true)) == -1) {
109 if( DEBUGLVL( 0 ) ) {
110 Debug1( "nmbd_subnetdb:make_subnet()\n" );
111 Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip
) );
112 Debug1( "for port %d. ", DGRAM_PORT
);
113 Debug1( "Error was %s\n", strerror(errno
) );
118 /* Make sure we can broadcast from these sockets. */
119 set_socket_options(nmb_sock
,"SO_BROADCAST");
120 set_socket_options(dgram_sock
,"SO_BROADCAST");
122 /* Set them non-blocking. */
123 set_blocking(nmb_sock
, False
);
124 set_blocking(dgram_sock
, False
);
127 subrec
= SMB_MALLOC_P(struct subnet_record
);
129 DEBUG(0,("make_subnet: malloc fail !\n"));
130 if (nmb_sock
!= -1) {
133 if (dgram_sock
!= -1) {
139 ZERO_STRUCTP(subrec
);
141 if((subrec
->subnet_name
= SMB_STRDUP(name
)) == NULL
) {
142 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
143 if (nmb_sock
!= -1) {
146 if (dgram_sock
!= -1) {
149 ZERO_STRUCTP(subrec
);
154 DEBUG(2, ("making subnet name:%s ", name
));
155 DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip
)));
156 DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip
)));
158 subrec
->namelist_changed
= False
;
159 subrec
->work_changed
= False
;
161 subrec
->bcast_ip
= bcast_ip
;
162 subrec
->mask_ip
= mask_ip
;
165 subrec
->nmb_sock
= nmb_sock
;
166 subrec
->dgram_sock
= dgram_sock
;
171 /****************************************************************************
172 Create a normal subnet
173 **************************************************************************/
175 struct subnet_record
*make_normal_subnet(const struct interface
*iface
)
178 struct subnet_record
*subrec
;
179 const struct in_addr
*pip
= &((const struct sockaddr_in
*)&iface
->ip
)->sin_addr
;
180 const struct in_addr
*pbcast
= &((const struct sockaddr_in
*)&iface
->bcast
)->sin_addr
;
181 const struct in_addr
*pnmask
= &((const struct sockaddr_in
*)&iface
->netmask
)->sin_addr
;
183 subrec
= make_subnet(inet_ntoa(*pip
), NORMAL_SUBNET
,
184 *pip
, *pbcast
, *pnmask
);
191 /****************************************************************************
192 Create subnet entries.
193 **************************************************************************/
195 bool create_subnets(void)
197 /* We only count IPv4 interfaces whilst we're waiting. */
198 int num_interfaces
= iface_count_v4();
200 struct in_addr unicast_ip
, ipzero
;
202 try_interfaces_again
:
204 if (iface_count_v4() == 0) {
205 DEBUG(0,("create_subnets: No local interfaces !\n"));
206 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
209 /* We only count IPv4 interfaces here. */
210 while (iface_count_v4() == 0) {
211 void (*saved_handler
)(int);
214 * Whilst we're waiting for an interface, allow SIGTERM to
218 saved_handler
= CatchSignal( SIGTERM
, SIGNAL_CAST SIG_DFL
);
224 * We got an interface, restore our normal term handler.
227 CatchSignal( SIGTERM
, SIGNAL_CAST saved_handler
);
231 * Here we count v4 and v6 - we know there's at least one
232 * IPv4 interface and we filter on it below.
234 num_interfaces
= iface_count();
237 * Create subnets from all the local interfaces and thread them onto
241 for (i
= 0 ; i
< num_interfaces
; i
++) {
242 const struct interface
*iface
= get_interface(i
);
245 DEBUG(2,("create_subnets: can't get interface %d.\n", i
));
249 /* Ensure we're only dealing with IPv4 here. */
250 if (iface
->ip
.ss_family
!= AF_INET
) {
251 DEBUG(2,("create_subnets: "
252 "ignoring non IPv4 interface.\n"));
257 * We don't want to add a loopback interface, in case
258 * someone has added 127.0.0.1 for smbd, nmbd needs to
259 * ignore it here. JRA.
262 if (is_loopback_addr(&iface
->ip
)) {
263 DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
267 if (!make_normal_subnet(iface
))
271 /* We must have at least one subnet. */
272 if (subnetlist
== NULL
) {
273 void (*saved_handler
)(int);
275 DEBUG(0,("create_subnets: Unable to create any subnet from "
276 "given interfaces. Is your interface line in "
277 "smb.conf correct ?\n"));
279 saved_handler
= CatchSignal( SIGTERM
, SIGNAL_CAST SIG_DFL
);
284 CatchSignal( SIGTERM
, SIGNAL_CAST saved_handler
);
285 goto try_interfaces_again
;
288 if (lp_we_are_a_wins_server()) {
289 /* Pick the first interface IPv4 address as the WINS server ip. */
290 const struct in_addr
*nip
= first_ipv4_iface();
298 /* note that we do not set the wins server IP here. We just
299 set it at zero and let the wins registration code cope
300 with getting the IPs right for each packet */
301 zero_ip_v4(&unicast_ip
);
305 * Create the unicast and remote broadcast subnets.
306 * Don't put these onto the linked list.
307 * The ip address of the unicast subnet is set to be
308 * the WINS server address, if it exists, or ipzero if not.
311 unicast_subnet
= make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET
,
312 unicast_ip
, unicast_ip
, unicast_ip
);
316 remote_broadcast_subnet
= make_subnet( "REMOTE_BROADCAST_SUBNET",
317 REMOTE_BROADCAST_SUBNET
,
318 ipzero
, ipzero
, ipzero
);
320 if((unicast_subnet
== NULL
) || (remote_broadcast_subnet
== NULL
))
324 * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
328 if (lp_we_are_a_wins_server()) {
329 if( (wins_server_subnet
= make_subnet( "WINS_SERVER_SUBNET",
331 ipzero
, ipzero
, ipzero
)) == NULL
)
338 /*******************************************************************
339 Function to tell us if we can use the unicast subnet.
340 ******************************************************************/
342 bool we_are_a_wins_client(void)
344 if (wins_srv_count() > 0) {
351 /*******************************************************************
352 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
353 ******************************************************************/
355 struct subnet_record
*get_next_subnet_maybe_unicast(struct subnet_record
*subrec
)
357 if(subrec
== unicast_subnet
)
359 else if((subrec
->next
== NULL
) && we_are_a_wins_client())
360 return unicast_subnet
;
365 /*******************************************************************
366 Access function used by retransmit_or_expire_response_records() in
367 nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
368 Needed when we need to enumerate all the broadcast, unicast and
370 ******************************************************************/
372 struct subnet_record
*get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record
*subrec
)
374 if(subrec
== unicast_subnet
) {
375 if(wins_server_subnet
)
376 return wins_server_subnet
;
381 if(wins_server_subnet
&& subrec
== wins_server_subnet
)
384 if((subrec
->next
== NULL
) && we_are_a_wins_client())
385 return unicast_subnet
;