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 struct in_addr loopback_ip;
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;
80 int nmb_sock, dgram_sock;
82 /* Check if we are creating a non broadcast subnet - if so don't create
85 if(type != NORMAL_SUBNET) {
90 * Attempt to open the sockets on port 137/138 for this interface
92 * Fail the subnet creation if this fails.
95 if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) {
97 Debug1( "nmbd_subnetdb:make_subnet()\n" );
98 Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) );
99 Debug1( "for port %d. ", global_nmb_port );
100 Debug1( "Error was %s\n", strerror(errno) );
105 if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) {
106 if( DEBUGLVL( 0 ) ) {
107 Debug1( "nmbd_subnetdb:make_subnet()\n" );
108 Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) );
109 Debug1( "for port %d. ", DGRAM_PORT );
110 Debug1( "Error was %s\n", strerror(errno) );
115 /* Make sure we can broadcast from these sockets. */
116 set_socket_options(nmb_sock,"SO_BROADCAST");
117 set_socket_options(dgram_sock,"SO_BROADCAST");
119 /* Set them non-blocking. */
120 set_blocking(nmb_sock, False);
121 set_blocking(dgram_sock, False);
124 subrec = SMB_MALLOC_P(struct subnet_record);
126 DEBUG(0,("make_subnet: malloc fail !\n"));
127 if (nmb_sock != -1) {
130 if (dgram_sock != -1) {
136 ZERO_STRUCTP(subrec);
138 if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
139 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
140 if (nmb_sock != -1) {
143 if (dgram_sock != -1) {
146 ZERO_STRUCTP(subrec);
151 DEBUG(2, ("making subnet name:%s ", name ));
152 DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
153 DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
155 subrec->namelist_changed = False;
156 subrec->work_changed = False;
158 subrec->bcast_ip = bcast_ip;
159 subrec->mask_ip = mask_ip;
162 subrec->nmb_sock = nmb_sock;
163 subrec->dgram_sock = dgram_sock;
168 /****************************************************************************
169 Create a normal subnet
170 **************************************************************************/
172 struct subnet_record *make_normal_subnet(struct interface *iface)
174 struct subnet_record *subrec;
176 subrec = make_subnet(inet_ntoa(iface->ip), NORMAL_SUBNET,
177 iface->ip, iface->bcast, iface->nmask);
184 /****************************************************************************
185 Create subnet entries.
186 **************************************************************************/
188 BOOL create_subnets(void)
190 int num_interfaces = iface_count();
192 struct in_addr unicast_ip, ipzero;
194 if(num_interfaces == 0) {
195 void (*saved_handler)(int);
197 DEBUG(0,("create_subnets: No local interfaces !\n"));
198 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
201 * Whilst we're waiting for an interface, allow SIGTERM to
205 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
207 while (iface_count() == 0) {
213 * We got an interface, restore our normal term handler.
216 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
219 num_interfaces = iface_count();
222 * Create subnets from all the local interfaces and thread them onto
226 for (i = 0 ; i < num_interfaces; i++) {
227 struct interface *iface = get_interface(i);
230 DEBUG(2,("create_subnets: can't get interface %d.\n", i ));
235 * We don't want to add a loopback interface, in case
236 * someone has added 127.0.0.1 for smbd, nmbd needs to
237 * ignore it here. JRA.
240 if (ip_equal(iface->ip, loopback_ip)) {
241 DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
245 if (!make_normal_subnet(iface))
249 /* We must have at least one subnet. */
250 if (subnetlist == NULL) {
251 DEBUG(0,("create_subnets: unable to create any subnet from "
252 "given interfaces. nmbd is terminating\n"));
256 if (lp_we_are_a_wins_server()) {
257 /* Pick the first interface ip address as the WINS server ip. */
258 struct in_addr *nip = iface_n_ip(0);
266 /* note that we do not set the wins server IP here. We just
267 set it at zero and let the wins registration code cope
268 with getting the IPs right for each packet */
269 zero_ip(&unicast_ip);
273 * Create the unicast and remote broadcast subnets.
274 * Don't put these onto the linked list.
275 * The ip address of the unicast subnet is set to be
276 * the WINS server address, if it exists, or ipzero if not.
279 unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
280 unicast_ip, unicast_ip, unicast_ip);
284 remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
285 REMOTE_BROADCAST_SUBNET,
286 ipzero, ipzero, ipzero);
288 if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
292 * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
296 if (lp_we_are_a_wins_server()) {
297 if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
299 ipzero, ipzero, ipzero )) == NULL )
306 /*******************************************************************
307 Function to tell us if we can use the unicast subnet.
308 ******************************************************************/
310 BOOL we_are_a_wins_client(void)
312 if (wins_srv_count() > 0) {
319 /*******************************************************************
320 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
321 ******************************************************************/
323 struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
325 if(subrec == unicast_subnet)
327 else if((subrec->next == NULL) && we_are_a_wins_client())
328 return unicast_subnet;
333 /*******************************************************************
334 Access function used by retransmit_or_expire_response_records() in
335 nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
336 Needed when we need to enumerate all the broadcast, unicast and
338 ******************************************************************/
340 struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
342 if(subrec == unicast_subnet) {
343 if(wins_server_subnet)
344 return wins_server_subnet;
349 if(wins_server_subnet && subrec == wins_server_subnet)
352 if((subrec->next == NULL) && we_are_a_wins_client())
353 return unicast_subnet;