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) {
89 * Attempt to open the sockets on port 137/138 for this interface
91 * Fail the subnet creation if this fails.
94 if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) {
96 Debug1( "nmbd_subnetdb:make_subnet()\n" );
97 Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) );
98 Debug1( "for port %d. ", global_nmb_port );
99 Debug1( "Error was %s\n", strerror(errno) );
104 if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) {
105 if( DEBUGLVL( 0 ) ) {
106 Debug1( "nmbd_subnetdb:make_subnet()\n" );
107 Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) );
108 Debug1( "for port %d. ", DGRAM_PORT );
109 Debug1( "Error was %s\n", strerror(errno) );
114 /* Make sure we can broadcast from these sockets. */
115 set_socket_options(nmb_sock,"SO_BROADCAST");
116 set_socket_options(dgram_sock,"SO_BROADCAST");
118 /* Set them non-blocking. */
119 set_blocking(nmb_sock, False);
120 set_blocking(dgram_sock, False);
123 subrec = SMB_MALLOC_P(struct subnet_record);
125 DEBUG(0,("make_subnet: malloc fail !\n"));
126 if (nmb_sock != -1) {
129 if (dgram_sock != -1) {
135 ZERO_STRUCTP(subrec);
137 if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
138 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
139 if (nmb_sock != -1) {
142 if (dgram_sock != -1) {
145 ZERO_STRUCTP(subrec);
150 DEBUG(2, ("making subnet name:%s ", name ));
151 DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
152 DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
154 subrec->namelist_changed = False;
155 subrec->work_changed = False;
157 subrec->bcast_ip = bcast_ip;
158 subrec->mask_ip = mask_ip;
161 subrec->nmb_sock = nmb_sock;
162 subrec->dgram_sock = dgram_sock;
167 /****************************************************************************
168 Create a normal subnet
169 **************************************************************************/
171 struct subnet_record *make_normal_subnet(const struct interface *iface)
174 struct subnet_record *subrec;
175 const struct in_addr *pip = &((const struct sockaddr_in *)&iface->ip)->sin_addr;
176 const struct in_addr *pbcast = &((const struct sockaddr_in *)&iface->bcast)->sin_addr;
177 const struct in_addr *pnmask = &((const struct sockaddr_in *)&iface->netmask)->sin_addr;
179 subrec = make_subnet(inet_ntoa(*pip), NORMAL_SUBNET,
180 *pip, *pbcast, *pnmask);
187 /****************************************************************************
188 Create subnet entries.
189 **************************************************************************/
191 BOOL create_subnets(void)
193 /* We only count IPv4 interfaces whilst we're waiting. */
194 int num_interfaces = iface_count_v4();
196 struct in_addr unicast_ip, ipzero;
198 if(num_interfaces == 0) {
199 void (*saved_handler)(int);
201 DEBUG(0,("create_subnets: No local interfaces !\n"));
202 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
205 * Whilst we're waiting for an interface, allow SIGTERM to
209 saved_handler = CatchSignal( SIGTERM, SIGNAL_CAST SIG_DFL );
211 /* We only count IPv4 interfaces here. */
212 while (iface_count_v4() == 0) {
218 * We got an interface, restore our normal term handler.
221 CatchSignal( SIGTERM, SIGNAL_CAST saved_handler );
225 * Here we count v4 and v6 - we know there's at least one
226 * IPv4 interface and we filter on it below.
228 num_interfaces = iface_count();
231 * Create subnets from all the local interfaces and thread them onto
235 for (i = 0 ; i < num_interfaces; i++) {
236 const struct interface *iface = get_interface(i);
239 DEBUG(2,("create_subnets: can't get interface %d.\n", i ));
243 /* Ensure we're only dealing with IPv4 here. */
244 if (iface->ip.ss_family != AF_INET) {
245 DEBUG(2,("create_subnets: "
246 "ignoring non IPv4 interface.\n"));
251 * We don't want to add a loopback interface, in case
252 * someone has added 127.0.0.1 for smbd, nmbd needs to
253 * ignore it here. JRA.
256 if (is_loopback_addr(&iface->ip)) {
257 DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
261 if (!make_normal_subnet(iface))
265 /* We must have at least one subnet. */
266 if (subnetlist == NULL) {
267 DEBUG(0,("create_subnets: unable to create any subnet from "
268 "given interfaces. nmbd is terminating\n"));
272 if (lp_we_are_a_wins_server()) {
273 /* Pick the first interface IPv4 address as the WINS server ip. */
274 const struct in_addr *nip = first_ipv4_iface();
282 /* note that we do not set the wins server IP here. We just
283 set it at zero and let the wins registration code cope
284 with getting the IPs right for each packet */
285 zero_ip_v4(&unicast_ip);
289 * Create the unicast and remote broadcast subnets.
290 * Don't put these onto the linked list.
291 * The ip address of the unicast subnet is set to be
292 * the WINS server address, if it exists, or ipzero if not.
295 unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
296 unicast_ip, unicast_ip, unicast_ip);
300 remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
301 REMOTE_BROADCAST_SUBNET,
302 ipzero, ipzero, ipzero);
304 if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
308 * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
312 if (lp_we_are_a_wins_server()) {
313 if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
315 ipzero, ipzero, ipzero )) == NULL )
322 /*******************************************************************
323 Function to tell us if we can use the unicast subnet.
324 ******************************************************************/
326 BOOL we_are_a_wins_client(void)
328 if (wins_srv_count() > 0) {
335 /*******************************************************************
336 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
337 ******************************************************************/
339 struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
341 if(subrec == unicast_subnet)
343 else if((subrec->next == NULL) && we_are_a_wins_client())
344 return unicast_subnet;
349 /*******************************************************************
350 Access function used by retransmit_or_expire_response_records() in
351 nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
352 Needed when we need to enumerate all the broadcast, unicast and
354 ******************************************************************/
356 struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
358 if(subrec == unicast_subnet) {
359 if(wins_server_subnet)
360 return wins_server_subnet;
365 if(wins_server_subnet && subrec == wins_server_subnet)
368 if((subrec->next == NULL) && we_are_a_wins_client())
369 return unicast_subnet;