r22972: added the basic ldif needed to support group policies in Samba4. WinXP
[Samba.git] / source / nbt_server / interfaces.c
blob09473f43c9524ea61a7386f7813c4819c6e96541
1 /*
2 Unix SMB/CIFS implementation.
4 NBT interface handling
6 Copyright (C) Andrew Tridgell 2005
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.
23 #include "includes.h"
24 #include "lib/util/dlinklist.h"
25 #include "nbt_server/nbt_server.h"
26 #include "smbd/service_task.h"
27 #include "lib/socket/socket.h"
28 #include "nbt_server/wins/winsserver.h"
29 #include "nbt_server/dgram/proto.h"
30 #include "system/network.h"
31 #include "lib/socket/netif.h"
35 receive an incoming request and dispatch it to the right place
37 static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
38 struct nbt_name_packet *packet,
39 struct socket_address *src)
41 struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
42 struct nbtd_interface);
43 struct nbtd_server *nbtsrv = iface->nbtsrv;
45 nbtsrv->stats.total_received++;
47 /* see if its from one of our own interfaces - if so, then ignore it */
48 if (nbtd_self_packet_and_bcast(nbtsock, packet, src)) {
49 DEBUG(10,("Ignoring bcast self packet from %s:%d\n", src->addr, src->port));
50 return;
53 switch (packet->operation & NBT_OPCODE) {
54 case NBT_OPCODE_QUERY:
55 nbtsrv->stats.query_count++;
56 nbtd_request_query(nbtsock, packet, src);
57 break;
59 case NBT_OPCODE_REGISTER:
60 case NBT_OPCODE_REFRESH:
61 case NBT_OPCODE_REFRESH2:
62 nbtsrv->stats.register_count++;
63 nbtd_request_defense(nbtsock, packet, src);
64 break;
66 case NBT_OPCODE_RELEASE:
67 case NBT_OPCODE_MULTI_HOME_REG:
68 nbtsrv->stats.release_count++;
69 nbtd_winsserver_request(nbtsock, packet, src);
70 break;
72 default:
73 nbtd_bad_packet(packet, src, "Unexpected opcode");
74 break;
80 find a registered name on an interface
82 struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface,
83 struct nbt_name *name,
84 uint16_t nb_flags)
86 struct nbtd_iface_name *iname;
87 for (iname=iface->names;iname;iname=iname->next) {
88 if (iname->name.type == name->type &&
89 strcmp(name->name, iname->name.name) == 0 &&
90 ((iname->nb_flags & nb_flags) == nb_flags)) {
91 return iname;
94 return NULL;
98 start listening on the given address
100 static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
101 const char *bind_address,
102 const char *address,
103 const char *bcast,
104 const char *netmask)
106 struct nbtd_interface *iface;
107 NTSTATUS status;
108 struct socket_address *bcast_address;
109 struct socket_address *unicast_address;
112 we actually create two sockets. One listens on the broadcast address
113 for the interface, and the other listens on our specific address. This
114 allows us to run with "bind interfaces only" while still receiving
115 broadcast addresses, and also simplifies matching incoming requests
116 to interfaces
119 iface = talloc(nbtsrv, struct nbtd_interface);
120 NT_STATUS_HAVE_NO_MEMORY(iface);
122 iface->nbtsrv = nbtsrv;
123 iface->bcast_address = talloc_steal(iface, bcast);
124 iface->ip_address = talloc_steal(iface, address);
125 iface->netmask = talloc_steal(iface, netmask);
126 iface->names = NULL;
128 if (strcmp(netmask, "0.0.0.0") != 0) {
129 struct nbt_name_socket *bcast_nbtsock;
131 /* listen for broadcasts on port 137 */
132 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
133 if (!bcast_nbtsock) {
134 talloc_free(iface);
135 return NT_STATUS_NO_MEMORY;
138 bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name,
139 bcast, lp_nbt_port());
140 if (!bcast_address) {
141 talloc_free(iface);
142 return NT_STATUS_NO_MEMORY;
145 status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0);
146 if (!NT_STATUS_IS_OK(status)) {
147 DEBUG(0,("Failed to bind to %s:%d - %s\n",
148 bcast, lp_nbt_port(), nt_errstr(status)));
149 talloc_free(iface);
150 return status;
152 talloc_free(bcast_address);
154 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
157 /* listen for unicasts on port 137 */
158 iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
159 if (!iface->nbtsock) {
160 talloc_free(iface);
161 return NT_STATUS_NO_MEMORY;
164 unicast_address = socket_address_from_strings(iface->nbtsock, iface->nbtsock->sock->backend_name,
165 bind_address, lp_nbt_port());
167 status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
168 if (!NT_STATUS_IS_OK(status)) {
169 DEBUG(0,("Failed to bind to %s:%d - %s\n",
170 bind_address, lp_nbt_port(), nt_errstr(status)));
171 talloc_free(iface);
172 return status;
174 talloc_free(unicast_address);
176 nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
178 /* also setup the datagram listeners */
179 status = nbtd_dgram_setup(iface, bind_address);
180 if (!NT_STATUS_IS_OK(status)) {
181 DEBUG(0,("Failed to setup dgram listen on %s - %s\n",
182 bind_address, nt_errstr(status)));
183 talloc_free(iface);
184 return status;
187 if (strcmp(netmask, "0.0.0.0") == 0) {
188 DLIST_ADD(nbtsrv->bcast_interface, iface);
189 } else {
190 DLIST_ADD(nbtsrv->interfaces, iface);
193 return NT_STATUS_OK;
197 setup a socket for talking to our WINS servers
199 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
201 struct nbtd_interface *iface;
203 iface = talloc_zero(nbtsrv, struct nbtd_interface);
204 NT_STATUS_HAVE_NO_MEMORY(iface);
206 iface->nbtsrv = nbtsrv;
208 DLIST_ADD(nbtsrv->wins_interface, iface);
210 return NT_STATUS_OK;
215 setup our listening sockets on the configured network interfaces
217 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
219 int num_interfaces = iface_count();
220 int i;
221 TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
222 NTSTATUS status;
224 /* if we are allowing incoming packets from any address, then
225 we also need to bind to the wildcard address */
226 if (!lp_bind_interfaces_only()) {
227 const char *primary_address;
229 /* the primary address is the address we will return
230 for non-WINS queries not made on a specific
231 interface */
232 if (num_interfaces > 0) {
233 primary_address = iface_n_ip(0);
234 } else {
235 primary_address = sys_inet_ntoa(interpret_addr2(
236 lp_netbios_name()));
238 primary_address = talloc_strdup(tmp_ctx, primary_address);
239 NT_STATUS_HAVE_NO_MEMORY(primary_address);
241 status = nbtd_add_socket(nbtsrv,
242 "0.0.0.0",
243 primary_address,
244 talloc_strdup(tmp_ctx, "255.255.255.255"),
245 talloc_strdup(tmp_ctx, "0.0.0.0"));
246 NT_STATUS_NOT_OK_RETURN(status);
249 for (i=0; i<num_interfaces; i++) {
250 const char *bcast = iface_n_bcast(i);
251 const char *address, *netmask;
253 /* we can't assume every interface is broadcast capable */
254 if (bcast == NULL) continue;
256 address = talloc_strdup(tmp_ctx, iface_n_ip(i));
257 bcast = talloc_strdup(tmp_ctx, bcast);
258 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(i));
260 status = nbtd_add_socket(nbtsrv, address, address, bcast, netmask);
261 NT_STATUS_NOT_OK_RETURN(status);
264 if (lp_wins_server_list()) {
265 status = nbtd_add_wins_socket(nbtsrv);
266 NT_STATUS_NOT_OK_RETURN(status);
269 talloc_free(tmp_ctx);
271 return NT_STATUS_OK;
276 form a list of addresses that we should use in name query replies
277 we always place the IP in the given interface first
279 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
281 struct nbtd_server *nbtsrv = iface->nbtsrv;
282 const char **ret = NULL;
283 struct nbtd_interface *iface2;
284 BOOL is_loopback = False;
286 if (iface->ip_address) {
287 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
288 ret = str_list_add(ret, iface->ip_address);
291 for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
292 if (iface2 == iface) continue;
294 if (!iface2->ip_address) continue;
296 if (!is_loopback) {
297 if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
298 continue;
302 ret = str_list_add(ret, iface2->ip_address);
305 talloc_steal(mem_ctx, ret);
307 return ret;
312 find the interface to use for sending a outgoing request
314 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
315 const char *address, BOOL allow_bcast_iface)
317 struct nbtd_interface *cur;
319 /* try to find a exact match */
320 for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
321 if (iface_same_net(address, cur->ip_address, cur->netmask)) {
322 return cur;
326 /* no exact match, if we have the broadcast interface, use that */
327 if (allow_bcast_iface && nbtd_server->bcast_interface) {
328 return nbtd_server->bcast_interface;
331 /* fallback to first interface */
332 return nbtd_server->interfaces;
336 * find the interface to use for sending a outgoing reply
338 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
339 const char *address, BOOL allow_bcast_iface)
341 struct nbtd_server *nbtd_server = iface->nbtsrv;
343 /* first try to use the given interfacel when it's not the broadcast one */
344 if (iface != nbtd_server->bcast_interface) {
345 return iface;
348 return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);