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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 extern int ClientDGRAM;
31 extern int global_nmb_port;
33 extern fstring myworkgroup;
34 extern char **my_netbios_names;
36 /* This is the broadcast subnets database. */
37 struct subnet_record *subnetlist = NULL;
39 /* Extra subnets - keep these separate so enumeration code doesn't
40 run onto it by mistake. */
42 struct subnet_record *unicast_subnet = NULL;
43 struct subnet_record *remote_broadcast_subnet = NULL;
44 struct subnet_record *wins_server_subnet = NULL;
46 extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
48 /****************************************************************************
49 Add a subnet into the list.
50 **************************************************************************/
52 static void add_subnet(struct subnet_record *subrec)
54 DLIST_ADD(subnetlist, subrec);
57 /* ************************************************************************** **
58 * Comparison routine for ordering the splay-tree based namelists assoicated
59 * with each subnet record.
61 * Input: Item - Pointer to the comparison key.
62 * Node - Pointer to a node the splay tree.
64 * Output: The return value will be <0 , ==0, or >0 depending upon the
65 * ordinal relationship of the two keys.
67 * ************************************************************************** **
69 static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node )
71 struct name_record *NR = (struct name_record *)Node;
75 struct nmb_name *Iname = (struct nmb_name *)Item;
77 Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" );
78 Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n",
79 memcmp( Item, &(NR->name), sizeof(struct nmb_name) ),
80 nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) );
83 return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) );
84 } /* namelist_entry_compare */
87 /****************************************************************************
88 stop listening on a subnet
89 we don't free the record as we don't have proper reference counting for it
90 yet and it may be in use by a response record
91 ****************************************************************************/
92 void close_subnet(struct subnet_record *subrec)
94 DLIST_REMOVE(subnetlist, subrec);
96 if (subrec->dgram_sock != -1) {
97 close(subrec->dgram_sock);
98 subrec->dgram_sock = -1;
100 if (subrec->nmb_sock != -1) {
101 close(subrec->nmb_sock);
102 subrec->nmb_sock = -1;
108 /****************************************************************************
109 Create a subnet entry.
110 ****************************************************************************/
112 static struct subnet_record *make_subnet(char *name, enum subnet_type type,
113 struct in_addr myip, struct in_addr bcast_ip,
114 struct in_addr mask_ip)
116 struct subnet_record *subrec = NULL;
117 int nmb_sock, dgram_sock;
119 /* Check if we are creating a non broadcast subnet - if so don't create
123 if(type != NORMAL_SUBNET)
131 * Attempt to open the sockets on port 137/138 for this interface
133 * Fail the subnet creation if this fails.
136 if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1)
140 Debug1( "nmbd_subnetdb:make_subnet()\n" );
141 Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) );
142 Debug1( "for port %d. ", global_nmb_port );
143 Debug1( "Error was %s\n", strerror(errno) );
148 if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1)
152 Debug1( "nmbd_subnetdb:make_subnet()\n" );
153 Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) );
154 Debug1( "for port %d. ", DGRAM_PORT );
155 Debug1( "Error was %s\n", strerror(errno) );
160 /* Make sure we can broadcast from these sockets. */
161 set_socket_options(nmb_sock,"SO_BROADCAST");
162 set_socket_options(dgram_sock,"SO_BROADCAST");
166 subrec = (struct subnet_record *)malloc(sizeof(*subrec));
170 DEBUG(0,("make_subnet: malloc fail !\n"));
176 memset( (char *)subrec, '\0', sizeof(*subrec) );
177 (void)ubi_trInitTree( subrec->namelist,
178 namelist_entry_compare,
181 if((subrec->subnet_name = strdup(name)) == NULL)
183 DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
186 ZERO_STRUCTP(subrec);
191 DEBUG(2, ("making subnet name:%s ", name ));
192 DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
193 DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
195 subrec->namelist_changed = False;
196 subrec->work_changed = False;
198 subrec->bcast_ip = bcast_ip;
199 subrec->mask_ip = mask_ip;
202 subrec->nmb_sock = nmb_sock;
203 subrec->dgram_sock = dgram_sock;
209 /****************************************************************************
210 Create a normal subnet
211 **************************************************************************/
212 struct subnet_record *make_normal_subnet(struct interface *iface)
214 struct subnet_record *subrec;
216 subrec = make_subnet(inet_ntoa(iface->ip), NORMAL_SUBNET,
217 iface->ip, iface->bcast, iface->nmask);
225 /****************************************************************************
226 Create subnet entries.
227 **************************************************************************/
229 BOOL create_subnets(void)
231 int num_interfaces = iface_count();
233 struct in_addr unicast_ip, ipzero;
234 extern struct in_addr loopback_ip;
236 if(num_interfaces == 0) {
237 DEBUG(0,("create_subnets: No local interfaces !\n"));
238 DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
239 while (iface_count() == 0) {
245 num_interfaces = iface_count();
248 * Create subnets from all the local interfaces and thread them onto
252 for (i = 0 ; i < num_interfaces; i++)
254 struct interface *iface = get_interface(i);
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 (ip_equal(iface->ip, loopback_ip)) {
263 DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
267 if (!make_normal_subnet(iface)) return False;
270 if (lp_we_are_a_wins_server()) {
271 /* Pick the first interface ip address as the WINS server ip. */
272 unicast_ip = *iface_n_ip(0);
274 /* note that we do not set the wins server IP here. We just
275 set it at zero and let the wins registration code cope
276 with getting the IPs right for each packet */
277 zero_ip(&unicast_ip);
281 * Create the unicast and remote broadcast subnets.
282 * Don't put these onto the linked list.
283 * The ip address of the unicast subnet is set to be
284 * the WINS server address, if it exists, or ipzero if not.
287 unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
288 unicast_ip, unicast_ip, unicast_ip);
292 remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
293 REMOTE_BROADCAST_SUBNET,
294 ipzero, ipzero, ipzero);
296 if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
300 * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
304 if (lp_we_are_a_wins_server())
306 if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
308 ipzero, ipzero, ipzero )) == NULL )
315 /*******************************************************************
316 Function to tell us if we can use the unicast subnet.
317 ******************************************************************/
318 BOOL we_are_a_wins_client(void)
320 if (wins_srv_count() > 0) {
327 /*******************************************************************
328 Access function used by NEXT_SUBNET_INCLUDING_UNICAST
329 ******************************************************************/
331 struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
333 if(subrec == unicast_subnet)
335 else if((subrec->next == NULL) && we_are_a_wins_client())
336 return unicast_subnet;
341 /*******************************************************************
342 Access function used by retransmit_or_expire_response_records() in
343 nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
344 Needed when we need to enumerate all the broadcast, unicast and
346 ******************************************************************/
348 struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
350 if(subrec == unicast_subnet)
352 if(wins_server_subnet)
353 return wins_server_subnet;
358 if(wins_server_subnet && subrec == wins_server_subnet)
361 if((subrec->next == NULL) && we_are_a_wins_client())
362 return unicast_subnet;