1 /*
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
7
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.
12
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.
17
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/>.
20
21 Revision History:
22
23 */
24
25 #include "includes.h"
26 #include "nmbd/nmbd.h"
27
28 extern int global_nmb_port;
29
30 /* This is the broadcast subnets database. */
31 struct subnet_record *subnetlist = NULL;
32
33 /* Extra subnets - keep these separate so enumeration code doesn't
34 run onto it by mistake. */
35
36 struct subnet_record *unicast_subnet = NULL;
37 struct subnet_record *remote_broadcast_subnet = NULL;
38 struct subnet_record *wins_server_subnet = NULL;
39
40 extern uint16_t samba_nb_type; /* Samba's NetBIOS name type. */
41
42 /****************************************************************************
43 Add a subnet into the list.
44 **************************************************************************/
45
add_subnet(struct subnet_record * subrec)46 static void add_subnet(struct subnet_record *subrec)
47 {
48 DLIST_ADD(subnetlist, subrec);
49 }
50
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 ****************************************************************************/
56
close_subnet(struct subnet_record * subrec)57 void close_subnet(struct subnet_record *subrec)
58 {
59 if (subrec->nmb_sock != -1) {
60 close(subrec->nmb_sock);
61 subrec->nmb_sock = -1;
62 }
63 if (subrec->nmb_bcast != -1) {
64 close(subrec->nmb_bcast);
65 subrec->nmb_bcast = -1;
66 }
67 if (subrec->dgram_sock != -1) {
68 close(subrec->dgram_sock);
69 subrec->dgram_sock = -1;
70 }
71 if (subrec->dgram_bcast != -1) {
72 close(subrec->dgram_bcast);
73 subrec->dgram_bcast = -1;
74 }
75
76 DLIST_REMOVE(subnetlist, subrec);
77 }
78
79 /****************************************************************************
80 Create a subnet entry.
81 ****************************************************************************/
82
make_subnet(const char * name,enum subnet_type type,struct in_addr myip,struct in_addr bcast_ip,struct in_addr mask_ip)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)
86 {
87 struct subnet_record *subrec = NULL;
88 int nmb_sock = -1;
89 int dgram_sock = -1;
90 int nmb_bcast = -1;
91 int dgram_bcast = -1;
92 bool bind_bcast = lp_nmbd_bind_explicit_broadcast();
93
94 /* Check if we are creating a non broadcast subnet - if so don't create
95 sockets. */
96
97 if (type == NORMAL_SUBNET) {
98 struct sockaddr_storage ss;
99 struct sockaddr_storage ss_bcast;
100
101 in_addr_to_sockaddr_storage(&ss, myip);
102 in_addr_to_sockaddr_storage(&ss_bcast, bcast_ip);
103
104 /*
105 * Attempt to open the sockets on port 137/138 for this interface
106 * and bind them.
107 * Fail the subnet creation if this fails.
108 */
109
110 nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,
111 0, &ss, true);
112 if (nmb_sock == -1) {
113 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
114 DEBUGADD(0,(" Failed to open nmb socket on interface %s ",
115 inet_ntoa(myip)));
116 DEBUGADD(0,("for port %d. ", global_nmb_port));
117 DEBUGADD(0,("Error was %s\n", strerror(errno)));
118 goto failed;
119 }
120 set_socket_options(nmb_sock,"SO_BROADCAST");
121 set_blocking(nmb_sock, false);
122
123 if (bind_bcast) {
124 nmb_bcast = open_socket_in(SOCK_DGRAM, global_nmb_port,
125 0, &ss_bcast, true);
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)));
132 goto failed;
133 }
134 set_socket_options(nmb_bcast, "SO_BROADCAST");
135 set_blocking(nmb_bcast, false);
136 }
137
138 dgram_sock = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
139 3, &ss, true);
140 if (dgram_sock == -1) {
141 DEBUG(0, ("nmbd_subnetdb:make_subnet()\n"));
142 DEBUGADD(0,(" Failed to open dgram socket on interface %s ",
143 inet_ntoa(myip)));
144 DEBUGADD(0,("for port %d. ", DGRAM_PORT));
145 DEBUGADD(0,("Error was %s\n", strerror(errno)));
146 goto failed;
147 }
148 set_socket_options(dgram_sock, "SO_BROADCAST");
149 set_blocking(dgram_sock, false);
150
151 if (bind_bcast) {
152 dgram_bcast = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
153 3, &ss_bcast, true);
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)));
160 goto failed;
161 }
162 set_socket_options(dgram_bcast, "SO_BROADCAST");
163 set_blocking(dgram_bcast, false);
164 }
165 }
166
167 subrec = SMB_MALLOC_P(struct subnet_record);
168 if (!subrec) {
169 DEBUG(0,("make_subnet: malloc fail !\n"));
170 goto failed;
171 }
172
173 ZERO_STRUCTP(subrec);
174
175 if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
176 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
177 goto failed;
178 }
179
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)));
183
184 subrec->namelist_changed = False;
185 subrec->work_changed = False;
186
187 subrec->bcast_ip = bcast_ip;
188 subrec->mask_ip = mask_ip;
189 subrec->myip = myip;
190 subrec->type = type;
191 subrec->nmb_sock = nmb_sock;
192 subrec->nmb_bcast = nmb_bcast;
193 subrec->dgram_sock = dgram_sock;
194 subrec->dgram_bcast = dgram_bcast;
195
196 return subrec;
197
198 failed:
199 SAFE_FREE(subrec);
200 if (nmb_sock != -1) {
201 close(nmb_sock);
202 }
203 if (nmb_bcast != -1) {
204 close(nmb_bcast);
205 }
206 if (dgram_sock != -1) {
207 close(dgram_sock);
208 }
209 if (dgram_bcast != -1) {
210 close(dgram_bcast);
211 }
212 return NULL;
213 }
214
215 /****************************************************************************
216 Create a normal subnet
217 **************************************************************************/
218
make_normal_subnet(const struct interface * iface)219 struct subnet_record *make_normal_subnet(const struct interface *iface)
220 {
221
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;
226
227 subrec = make_subnet(inet_ntoa(*pip), NORMAL_SUBNET,
228 *pip, *pbcast, *pnmask);
229 if (subrec) {
230 add_subnet(subrec);
231 }
232 return subrec;
233 }
234
235 /****************************************************************************
236 Create subnet entries.
237 **************************************************************************/
238
create_subnets(void)239 bool create_subnets(void)
240 {
241 /* We only count IPv4 interfaces whilst we're waiting. */
242 int num_interfaces;
243 int i;
244 struct in_addr unicast_ip, ipzero;
245
246 try_interfaces_again:
247
248 /* Only count IPv4, non-loopback interfaces. */
249 if (iface_count_v4_nl() == 0) {
250 daemon_status("nmbd",
251 "No local IPv4 non-loopback interfaces "
252 "available, waiting for interface ...");
253 DEBUG(0,("NOTE: NetBIOS name resolution is not supported for "
254 "Internet Protocol Version 6 (IPv6).\n"));
255 }
256
257 /* We only count IPv4, non-loopback interfaces here. */
258 while (iface_count_v4_nl() == 0) {
259 void (*saved_handler)(int);
260
261 /*
262 * Whilst we're waiting for an interface, allow SIGTERM to
263 * cause us to exit.
264 */
265
266 saved_handler = CatchSignal(SIGTERM, SIG_DFL);
267
268 sleep(5);
269 load_interfaces();
270
271 /*
272 * We got an interface, restore our normal term handler.
273 */
274
275 CatchSignal(SIGTERM, saved_handler);
276 }
277
278 /*
279 * Here we count v4 and v6 - we know there's at least one
280 * IPv4 interface and we filter on it below.
281 */
282 num_interfaces = iface_count();
283
284 /*
285 * Create subnets from all the local interfaces and thread them onto
286 * the linked list.
287 */
288
289 for (i = 0 ; i < num_interfaces; i++) {
290 const struct interface *iface = get_interface(i);
291
292 if (!iface) {
293 DEBUG(2,("create_subnets: can't get interface %d.\n", i ));
294 continue;
295 }
296
297 /* Ensure we're only dealing with IPv4 here. */
298 if (iface->ip.ss_family != AF_INET) {
299 DEBUG(2,("create_subnets: "
300 "ignoring non IPv4 interface.\n"));
301 continue;
302 }
303
304 /*
305 * We don't want to add a loopback interface, in case
306 * someone has added 127.0.0.1 for smbd, nmbd needs to
307 * ignore it here. JRA.
308 */
309
310 if (is_loopback_addr((const struct sockaddr *)&iface->ip)) {
311 DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
312 continue;
313 }
314
315 if (!make_normal_subnet(iface))
316 return False;
317 }
318
319 /* We must have at least one subnet. */
320 if (subnetlist == NULL) {
321 void (*saved_handler)(int);
322
323 DEBUG(0,("create_subnets: Unable to create any subnet from "
324 "given interfaces. Is your interface line in "
325 "smb.conf correct ?\n"));
326
327 saved_handler = CatchSignal(SIGTERM, SIG_DFL);
328
329 sleep(5);
330 load_interfaces();
331
332 CatchSignal(SIGTERM, saved_handler);
333 goto try_interfaces_again;
334 }
335
336 if (lp_we_are_a_wins_server()) {
337 /* Pick the first interface IPv4 address as the WINS server
338 * ip. */
339 const struct in_addr *nip = first_ipv4_iface();
340
341 if (!nip) {
342 return False;
343 }
344
345 unicast_ip = *nip;
346 } else {
347 /* note that we do not set the wins server IP here. We just
348 set it at zero and let the wins registration code cope
349 with getting the IPs right for each packet */
350 zero_ip_v4(&unicast_ip);
351 }
352
353 /*
354 * Create the unicast and remote broadcast subnets.
355 * Don't put these onto the linked list.
356 * The ip address of the unicast subnet is set to be
357 * the WINS server address, if it exists, or ipzero if not.
358 */
359
360 unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
361 unicast_ip, unicast_ip, unicast_ip);
362
363 zero_ip_v4(&ipzero);
364
365 remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
366 REMOTE_BROADCAST_SUBNET,
367 ipzero, ipzero, ipzero);
368
369 if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
370 return False;
371
372 /*
373 * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
374 * the linked list.
375 */
376
377 if (lp_we_are_a_wins_server()) {
378 if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
379 WINS_SERVER_SUBNET,
380 ipzero, ipzero, ipzero )) == NULL )
381 return False;
382 }
383
384 return True;
385 }
386
387 /*******************************************************************
388 Function to tell us if we can use the unicast subnet.
389 ******************************************************************/
390
we_are_a_wins_client(void)391 bool we_are_a_wins_client(void)
392 {
393 if (wins_srv_count() > 0) {
394 return True;
395 }
396
397 return False;
398 }
399
400 /*******************************************************************
401 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
402 ******************************************************************/
403
get_next_subnet_maybe_unicast(struct subnet_record * subrec)404 struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
405 {
406 if(subrec == unicast_subnet)
407 return NULL;
408 else if((subrec->next == NULL) && we_are_a_wins_client())
409 return unicast_subnet;
410 else
411 return subrec->next;
412 }
413
414 /*******************************************************************
415 Access function used by retransmit_or_expire_response_records() in
416 nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
417 Needed when we need to enumerate all the broadcast, unicast and
418 WINS subnets.
419 ******************************************************************/
420
get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record * subrec)421 struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
422 {
423 if(subrec == unicast_subnet) {
424 if(wins_server_subnet)
425 return wins_server_subnet;
426 else
427 return NULL;
428 }
429
430 if(wins_server_subnet && subrec == wins_server_subnet)
431 return NULL;
432
433 if((subrec->next == NULL) && we_are_a_wins_client())
434 return unicast_subnet;
435 else
436 return subrec->next;
437 }
438