2 Unix SMB/CIFS implementation.
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 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/>.
23 #include "../lib/util/dlinklist.h"
24 #include "nbt_server/nbt_server.h"
25 #include "smbd/service_task.h"
26 #include "lib/socket/socket.h"
27 #include "nbt_server/wins/winsserver.h"
28 #include "nbt_server/dgram/proto.h"
29 #include "system/network.h"
30 #include "lib/socket/netif.h"
31 #include "param/param.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_data,
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));
53 switch (packet->operation & NBT_OPCODE) {
54 case NBT_OPCODE_QUERY:
55 nbtsrv->stats.query_count++;
56 nbtd_request_query(nbtsock, packet, src);
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);
66 case NBT_OPCODE_RELEASE:
67 case NBT_OPCODE_MULTI_HOME_REG:
68 nbtsrv->stats.release_count++;
69 nbtd_winsserver_request(nbtsock, packet, src);
73 nbtd_bad_packet(packet, src, "Unexpected opcode");
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,
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)) {
98 start listening on the given address
100 static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
101 struct loadparm_context *lp_ctx,
102 const char *bind_address,
107 struct nbtd_interface *iface;
109 struct socket_address *bcast_address;
110 struct socket_address *unicast_address;
112 DEBUG(6,("nbtd_add_socket(%s, %s, %s, %s)\n", bind_address, address, bcast, netmask));
115 we actually create two sockets. One listens on the broadcast address
116 for the interface, and the other listens on our specific address. This
117 allows us to run with "bind interfaces only" while still receiving
118 broadcast addresses, and also simplifies matching incoming requests
122 iface = talloc(nbtsrv, struct nbtd_interface);
123 NT_STATUS_HAVE_NO_MEMORY(iface);
125 iface->nbtsrv = nbtsrv;
126 iface->bcast_address = talloc_steal(iface, bcast);
127 iface->ip_address = talloc_steal(iface, address);
128 iface->netmask = talloc_steal(iface, netmask);
130 iface->wack_queue = NULL;
132 if (strcmp(netmask, "0.0.0.0") != 0) {
133 struct nbt_name_socket *bcast_nbtsock;
135 /* listen for broadcasts on port 137 */
136 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx, lp_iconv_convenience(nbtsrv->task->lp_ctx));
137 if (!bcast_nbtsock) {
139 return NT_STATUS_NO_MEMORY;
142 bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name,
143 bcast, lp_nbt_port(lp_ctx));
144 if (!bcast_address) {
146 return NT_STATUS_NO_MEMORY;
149 status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0);
150 if (!NT_STATUS_IS_OK(status)) {
151 DEBUG(0,("Failed to bind to %s:%d - %s\n",
152 bcast, lp_nbt_port(lp_ctx), nt_errstr(status)));
156 talloc_free(bcast_address);
158 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
161 /* listen for unicasts on port 137 */
162 iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx,
163 lp_iconv_convenience(nbtsrv->task->lp_ctx));
164 if (!iface->nbtsock) {
166 return NT_STATUS_NO_MEMORY;
169 unicast_address = socket_address_from_strings(iface->nbtsock,
170 iface->nbtsock->sock->backend_name,
171 bind_address, lp_nbt_port(lp_ctx));
173 status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
174 if (!NT_STATUS_IS_OK(status)) {
175 DEBUG(0,("Failed to bind to %s:%d - %s\n",
176 bind_address, lp_nbt_port(lp_ctx), nt_errstr(status)));
180 talloc_free(unicast_address);
182 nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
184 /* also setup the datagram listeners */
185 status = nbtd_dgram_setup(iface, bind_address);
186 if (!NT_STATUS_IS_OK(status)) {
187 DEBUG(0,("Failed to setup dgram listen on %s - %s\n",
188 bind_address, nt_errstr(status)));
193 if (strcmp(netmask, "0.0.0.0") == 0) {
194 DLIST_ADD(nbtsrv->bcast_interface, iface);
196 DLIST_ADD(nbtsrv->interfaces, iface);
203 setup a socket for talking to our WINS servers
205 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
207 struct nbtd_interface *iface;
209 iface = talloc_zero(nbtsrv, struct nbtd_interface);
210 NT_STATUS_HAVE_NO_MEMORY(iface);
212 iface->nbtsrv = nbtsrv;
214 DLIST_ADD(nbtsrv->wins_interface, iface);
221 setup our listening sockets on the configured network interfaces
223 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx,
224 struct interface *ifaces)
226 int num_interfaces = iface_count(ifaces);
228 TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
231 /* if we are allowing incoming packets from any address, then
232 we also need to bind to the wildcard address */
233 if (!lp_bind_interfaces_only(lp_ctx)) {
234 const char *primary_address;
236 /* the primary address is the address we will return
237 for non-WINS queries not made on a specific
239 if (num_interfaces > 0) {
240 primary_address = iface_n_ip(ifaces, 0);
242 primary_address = inet_ntoa(interpret_addr2(
243 lp_netbios_name(lp_ctx)));
245 primary_address = talloc_strdup(tmp_ctx, primary_address);
246 NT_STATUS_HAVE_NO_MEMORY(primary_address);
248 status = nbtd_add_socket(nbtsrv,
252 talloc_strdup(tmp_ctx, "255.255.255.255"),
253 talloc_strdup(tmp_ctx, "0.0.0.0"));
254 NT_STATUS_NOT_OK_RETURN(status);
257 for (i=0; i<num_interfaces; i++) {
258 const char *bcast = iface_n_bcast(ifaces, i);
259 const char *address, *netmask;
261 /* we can't assume every interface is broadcast capable */
262 if (bcast == NULL) continue;
264 address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
265 bcast = talloc_strdup(tmp_ctx, bcast);
266 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(ifaces, i));
268 status = nbtd_add_socket(nbtsrv, lp_ctx,
269 address, address, bcast, netmask);
270 NT_STATUS_NOT_OK_RETURN(status);
273 if (lp_wins_server_list(lp_ctx)) {
274 status = nbtd_add_wins_socket(nbtsrv);
275 NT_STATUS_NOT_OK_RETURN(status);
278 talloc_free(tmp_ctx);
285 form a list of addresses that we should use in name query replies
286 we always place the IP in the given interface first
288 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
290 struct nbtd_server *nbtsrv = iface->nbtsrv;
291 const char **ret = NULL;
292 struct nbtd_interface *iface2;
293 bool is_loopback = false;
295 if (iface->ip_address) {
296 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
297 ret = str_list_add(ret, iface->ip_address);
300 for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
301 if (iface2 == iface) continue;
303 if (!iface2->ip_address) continue;
306 if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
311 ret = str_list_add(ret, iface2->ip_address);
314 talloc_steal(mem_ctx, ret);
321 find the interface to use for sending a outgoing request
323 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
324 const char *address, bool allow_bcast_iface)
326 struct nbtd_interface *cur;
328 /* try to find a exact match */
329 for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
330 if (iface_same_net(address, cur->ip_address, cur->netmask)) {
331 DEBUG(10,("find interface for dst[%s] ip: %s/%s (iface[%p])\n",
332 address, cur->ip_address, cur->netmask, cur));
337 /* no exact match, if we have the broadcast interface, use that */
338 if (allow_bcast_iface && nbtd_server->bcast_interface) {
339 cur = nbtd_server->bcast_interface;
340 DEBUG(10,("find interface for dst[%s] ip: %s/%s (bcast iface[%p])\n",
341 address, cur->ip_address, cur->netmask, cur));
345 /* fallback to first interface */
346 cur = nbtd_server->interfaces;
347 DEBUG(10,("find interface for dst[%s] ip: %s/%s (default iface[%p])\n",
348 address, cur->ip_address, cur->netmask, cur));
353 * find the interface to use for sending a outgoing reply
355 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
356 const char *address, bool allow_bcast_iface)
358 struct nbtd_server *nbtd_server = iface->nbtsrv;
360 /* first try to use the given interfacel when it's not the broadcast one */
361 if (iface != nbtd_server->bcast_interface) {
365 return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);