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;
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);
128 iface->wack_queue = NULL;
130 if (strcmp(netmask, "0.0.0.0") != 0) {
131 struct nbt_name_socket *bcast_nbtsock;
133 /* listen for broadcasts on port 137 */
134 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx, lp_iconv_convenience(nbtsrv->task->lp_ctx));
135 if (!bcast_nbtsock) {
137 return NT_STATUS_NO_MEMORY;
140 bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name,
141 bcast, lp_nbt_port(lp_ctx));
142 if (!bcast_address) {
144 return NT_STATUS_NO_MEMORY;
147 status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0);
148 if (!NT_STATUS_IS_OK(status)) {
149 DEBUG(0,("Failed to bind to %s:%d - %s\n",
150 bcast, lp_nbt_port(lp_ctx), nt_errstr(status)));
154 talloc_free(bcast_address);
156 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
159 /* listen for unicasts on port 137 */
160 iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx,
161 lp_iconv_convenience(nbtsrv->task->lp_ctx));
162 if (!iface->nbtsock) {
164 return NT_STATUS_NO_MEMORY;
167 unicast_address = socket_address_from_strings(iface->nbtsock,
168 iface->nbtsock->sock->backend_name,
169 bind_address, lp_nbt_port(lp_ctx));
171 status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
172 if (!NT_STATUS_IS_OK(status)) {
173 DEBUG(0,("Failed to bind to %s:%d - %s\n",
174 bind_address, lp_nbt_port(lp_ctx), nt_errstr(status)));
178 talloc_free(unicast_address);
180 nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
182 /* also setup the datagram listeners */
183 status = nbtd_dgram_setup(iface, bind_address);
184 if (!NT_STATUS_IS_OK(status)) {
185 DEBUG(0,("Failed to setup dgram listen on %s - %s\n",
186 bind_address, nt_errstr(status)));
191 if (strcmp(netmask, "0.0.0.0") == 0) {
192 DLIST_ADD(nbtsrv->bcast_interface, iface);
194 DLIST_ADD(nbtsrv->interfaces, iface);
201 setup a socket for talking to our WINS servers
203 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
205 struct nbtd_interface *iface;
207 iface = talloc_zero(nbtsrv, struct nbtd_interface);
208 NT_STATUS_HAVE_NO_MEMORY(iface);
210 iface->nbtsrv = nbtsrv;
212 DLIST_ADD(nbtsrv->wins_interface, iface);
219 setup our listening sockets on the configured network interfaces
221 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx,
222 struct interface *ifaces)
224 int num_interfaces = iface_count(ifaces);
226 TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
229 /* if we are allowing incoming packets from any address, then
230 we also need to bind to the wildcard address */
231 if (!lp_bind_interfaces_only(lp_ctx)) {
232 const char *primary_address;
234 /* the primary address is the address we will return
235 for non-WINS queries not made on a specific
237 if (num_interfaces > 0) {
238 primary_address = iface_n_ip(ifaces, 0);
240 primary_address = inet_ntoa(interpret_addr2(
241 lp_netbios_name(lp_ctx)));
243 primary_address = talloc_strdup(tmp_ctx, primary_address);
244 NT_STATUS_HAVE_NO_MEMORY(primary_address);
246 status = nbtd_add_socket(nbtsrv,
250 talloc_strdup(tmp_ctx, "255.255.255.255"),
251 talloc_strdup(tmp_ctx, "0.0.0.0"));
252 NT_STATUS_NOT_OK_RETURN(status);
255 for (i=0; i<num_interfaces; i++) {
256 const char *bcast = iface_n_bcast(ifaces, i);
257 const char *address, *netmask;
259 /* we can't assume every interface is broadcast capable */
260 if (bcast == NULL) continue;
262 address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
263 bcast = talloc_strdup(tmp_ctx, bcast);
264 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(ifaces, i));
266 status = nbtd_add_socket(nbtsrv, lp_ctx,
267 address, address, bcast, netmask);
268 NT_STATUS_NOT_OK_RETURN(status);
271 if (lp_wins_server_list(lp_ctx)) {
272 status = nbtd_add_wins_socket(nbtsrv);
273 NT_STATUS_NOT_OK_RETURN(status);
276 talloc_free(tmp_ctx);
283 form a list of addresses that we should use in name query replies
284 we always place the IP in the given interface first
286 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
288 struct nbtd_server *nbtsrv = iface->nbtsrv;
289 const char **ret = NULL;
290 struct nbtd_interface *iface2;
291 bool is_loopback = false;
293 if (iface->ip_address) {
294 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
295 ret = str_list_add(ret, iface->ip_address);
298 for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
299 if (iface2 == iface) continue;
301 if (!iface2->ip_address) continue;
304 if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
309 ret = str_list_add(ret, iface2->ip_address);
312 talloc_steal(mem_ctx, ret);
319 find the interface to use for sending a outgoing request
321 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
322 const char *address, bool allow_bcast_iface)
324 struct nbtd_interface *cur;
326 /* try to find a exact match */
327 for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
328 if (iface_same_net(address, cur->ip_address, cur->netmask)) {
333 /* no exact match, if we have the broadcast interface, use that */
334 if (allow_bcast_iface && nbtd_server->bcast_interface) {
335 return nbtd_server->bcast_interface;
338 /* fallback to first interface */
339 return nbtd_server->interfaces;
343 * find the interface to use for sending a outgoing reply
345 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
346 const char *address, bool allow_bcast_iface)
348 struct nbtd_server *nbtd_server = iface->nbtsrv;
350 /* first try to use the given interfacel when it's not the broadcast one */
351 if (iface != nbtd_server->bcast_interface) {
355 return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface);