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,
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;
113 we actually create two sockets. One listens on the broadcast address
114 for the interface, and the other listens on our specific address. This
115 allows us to run with "bind interfaces only" while still receiving
116 broadcast addresses, and also simplifies matching incoming requests
120 iface = talloc(nbtsrv, struct nbtd_interface);
121 NT_STATUS_HAVE_NO_MEMORY(iface);
123 iface->nbtsrv = nbtsrv;
124 iface->bcast_address = talloc_steal(iface, bcast);
125 iface->ip_address = talloc_steal(iface, address);
126 iface->netmask = talloc_steal(iface, netmask);
129 if (strcmp(netmask, "0.0.0.0") != 0) {
130 struct nbt_name_socket *bcast_nbtsock;
132 /* listen for broadcasts on port 137 */
133 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
134 if (!bcast_nbtsock) {
136 return NT_STATUS_NO_MEMORY;
139 bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name,
140 bcast, lp_nbt_port(lp_ctx));
141 if (!bcast_address) {
143 return NT_STATUS_NO_MEMORY;
146 status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0);
147 if (!NT_STATUS_IS_OK(status)) {
148 DEBUG(0,("Failed to bind to %s:%d - %s\n",
149 bcast, lp_nbt_port(lp_ctx), nt_errstr(status)));
153 talloc_free(bcast_address);
155 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
158 /* listen for unicasts on port 137 */
159 iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
160 if (!iface->nbtsock) {
162 return NT_STATUS_NO_MEMORY;
165 unicast_address = socket_address_from_strings(iface->nbtsock,
166 iface->nbtsock->sock->backend_name,
167 bind_address, lp_nbt_port(lp_ctx));
169 status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
170 if (!NT_STATUS_IS_OK(status)) {
171 DEBUG(0,("Failed to bind to %s:%d - %s\n",
172 bind_address, lp_nbt_port(lp_ctx), nt_errstr(status)));
176 talloc_free(unicast_address);
178 nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
180 /* also setup the datagram listeners */
181 status = nbtd_dgram_setup(iface, bind_address);
182 if (!NT_STATUS_IS_OK(status)) {
183 DEBUG(0,("Failed to setup dgram listen on %s - %s\n",
184 bind_address, nt_errstr(status)));
189 if (strcmp(netmask, "0.0.0.0") == 0) {
190 DLIST_ADD(nbtsrv->bcast_interface, iface);
192 DLIST_ADD(nbtsrv->interfaces, iface);
199 setup a socket for talking to our WINS servers
201 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
203 struct nbtd_interface *iface;
205 iface = talloc_zero(nbtsrv, struct nbtd_interface);
206 NT_STATUS_HAVE_NO_MEMORY(iface);
208 iface->nbtsrv = nbtsrv;
210 DLIST_ADD(nbtsrv->wins_interface, iface);
217 setup our listening sockets on the configured network interfaces
219 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx)
221 int num_interfaces = iface_count();
223 TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
226 /* if we are allowing incoming packets from any address, then
227 we also need to bind to the wildcard address */
228 if (!lp_bind_interfaces_only(lp_ctx)) {
229 const char *primary_address;
231 /* the primary address is the address we will return
232 for non-WINS queries not made on a specific
234 if (num_interfaces > 0) {
235 primary_address = iface_n_ip(0);
237 primary_address = inet_ntoa(interpret_addr2(
238 lp_netbios_name(lp_ctx)));
240 primary_address = talloc_strdup(tmp_ctx, primary_address);
241 NT_STATUS_HAVE_NO_MEMORY(primary_address);
243 status = nbtd_add_socket(nbtsrv,
247 talloc_strdup(tmp_ctx, "255.255.255.255"),
248 talloc_strdup(tmp_ctx, "0.0.0.0"));
249 NT_STATUS_NOT_OK_RETURN(status);
252 for (i=0; i<num_interfaces; i++) {
253 const char *bcast = iface_n_bcast(i);
254 const char *address, *netmask;
256 /* we can't assume every interface is broadcast capable */
257 if (bcast == NULL) continue;
259 address = talloc_strdup(tmp_ctx, iface_n_ip(i));
260 bcast = talloc_strdup(tmp_ctx, bcast);
261 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(i));
263 status = nbtd_add_socket(nbtsrv, lp_ctx,
264 address, address, bcast, netmask);
265 NT_STATUS_NOT_OK_RETURN(status);
268 if (lp_wins_server_list(lp_ctx)) {
269 status = nbtd_add_wins_socket(nbtsrv);
270 NT_STATUS_NOT_OK_RETURN(status);
273 talloc_free(tmp_ctx);
280 form a list of addresses that we should use in name query replies
281 we always place the IP in the given interface first
283 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
285 struct nbtd_server *nbtsrv = iface->nbtsrv;
286 const char **ret = NULL;
287 struct nbtd_interface *iface2;
288 bool is_loopback = false;
290 if (iface->ip_address) {
291 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
292 ret = str_list_add(ret, iface->ip_address);
295 for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
296 if (iface2 == iface) continue;
298 if (!iface2->ip_address) continue;
301 if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
306 ret = str_list_add(ret, iface2->ip_address);
309 talloc_steal(mem_ctx, ret);
316 find the interface to use for sending a outgoing request
318 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
319 const char *address, bool allow_bcast_iface)
321 struct nbtd_interface *cur;
323 /* try to find a exact match */
324 for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
325 if (iface_same_net(address, cur->ip_address, cur->netmask)) {
330 /* no exact match, if we have the broadcast interface, use that */
331 if (allow_bcast_iface && nbtd_server->bcast_interface) {
332 return nbtd_server->bcast_interface;
335 /* fallback to first interface */
336 return nbtd_server->interfaces;
340 * find the interface to use for sending a outgoing reply
342 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
343 const char *address, bool allow_bcast_iface)
345 struct nbtd_server *nbtd_server = iface->nbtsrv;
347 /* first try to use the given interfacel when it's not the broadcast one */
348 if (iface != nbtd_server->bcast_interface) {
352 return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);