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 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.
24 #include "dlinklist.h"
25 #include "nbt_server/nbt_server.h"
26 #include "smbd/service_task.h"
27 #include "lib/socket/socket.h"
31 receive an incoming request and dispatch it to the right place
33 static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
34 struct nbt_name_packet *packet,
35 const struct nbt_peer_socket *src)
37 struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
38 struct nbtd_interface);
39 struct nbtd_server *nbtsrv = iface->nbtsrv;
41 nbtsrv->stats.total_received++;
43 /* see if its from one of our own interfaces - if so, then ignore it */
44 if (nbtd_self_packet(nbtsock, packet, src)) {
45 DEBUG(10,("Ignoring self packet from %s:%d\n", src->addr, src->port));
49 switch (packet->operation & NBT_OPCODE) {
50 case NBT_OPCODE_QUERY:
51 nbtsrv->stats.query_count++;
52 nbtd_request_query(nbtsock, packet, src);
55 case NBT_OPCODE_REGISTER:
56 case NBT_OPCODE_REFRESH:
57 case NBT_OPCODE_REFRESH2:
58 nbtsrv->stats.register_count++;
59 nbtd_request_defense(nbtsock, packet, src);
62 case NBT_OPCODE_RELEASE:
63 case NBT_OPCODE_MULTI_HOME_REG:
64 nbtsrv->stats.release_count++;
65 nbtd_winsserver_request(nbtsock, packet, src);
69 nbtd_bad_packet(packet, src, "Unexpected opcode");
76 find a registered name on an interface
78 struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface,
79 struct nbt_name *name,
82 struct nbtd_iface_name *iname;
83 for (iname=iface->names;iname;iname=iname->next) {
84 if (iname->name.type == name->type &&
85 strcmp(name->name, iname->name.name) == 0 &&
86 ((iname->nb_flags & nb_flags) == nb_flags)) {
94 start listening on the given address
96 static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
97 const char *bind_address,
102 struct nbtd_interface *iface;
106 we actually create two sockets. One listens on the broadcast address
107 for the interface, and the other listens on our specific address. This
108 allows us to run with "bind interfaces only" while still receiving
109 broadcast addresses, and also simplifies matching incoming requests
113 iface = talloc(nbtsrv, struct nbtd_interface);
114 NT_STATUS_HAVE_NO_MEMORY(iface);
116 iface->nbtsrv = nbtsrv;
117 iface->bcast_address = talloc_steal(iface, bcast);
118 iface->ip_address = talloc_steal(iface, address);
119 iface->netmask = talloc_steal(iface, netmask);
122 if (strcmp(netmask, "0.0.0.0") != 0) {
123 struct nbt_name_socket *bcast_nbtsock;
125 /* listen for broadcasts on port 137 */
126 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
127 NT_STATUS_HAVE_NO_MEMORY(bcast_nbtsock);
129 status = socket_listen(bcast_nbtsock->sock, bcast, lp_nbt_port(), 0, 0);
130 if (!NT_STATUS_IS_OK(status)) {
131 DEBUG(0,("Failed to bind to %s:%d - %s\n",
132 bcast, lp_nbt_port(), nt_errstr(status)));
137 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface);
140 /* listen for unicasts on port 137 */
141 iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
142 NT_STATUS_HAVE_NO_MEMORY(iface->nbtsock);
144 status = socket_listen(iface->nbtsock->sock, bind_address, lp_nbt_port(), 0, 0);
145 if (!NT_STATUS_IS_OK(status)) {
146 DEBUG(0,("Failed to bind to %s:%d - %s\n",
147 bind_address, lp_nbt_port(), nt_errstr(status)));
151 nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
153 /* also setup the datagram listeners */
154 status = nbtd_dgram_setup(iface, bind_address);
155 if (!NT_STATUS_IS_OK(status)) {
156 DEBUG(0,("Failed to setup dgram listen on %s - %s\n",
157 bind_address, nt_errstr(status)));
162 if (strcmp(netmask, "0.0.0.0") == 0) {
163 DLIST_ADD(nbtsrv->bcast_interface, iface);
165 DLIST_ADD(nbtsrv->interfaces, iface);
173 setup a socket for talking to our WINS servers
175 static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
177 struct nbtd_interface *iface;
179 iface = talloc_zero(nbtsrv, struct nbtd_interface);
180 NT_STATUS_HAVE_NO_MEMORY(iface);
182 iface->nbtsrv = nbtsrv;
184 DLIST_ADD(nbtsrv->wins_interface, iface);
191 setup our listening sockets on the configured network interfaces
193 NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
195 int num_interfaces = iface_count();
197 TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
200 /* if we are allowing incoming packets from any address, then
201 we also need to bind to the wildcard address */
202 if (!lp_bind_interfaces_only()) {
203 const char *primary_address;
205 /* the primary address is the address we will return
206 for non-WINS queries not made on a specific
208 if (num_interfaces > 0) {
209 primary_address = iface_n_ip(0);
211 primary_address = sys_inet_ntoa(interpret_addr2(
214 primary_address = talloc_strdup(tmp_ctx, primary_address);
215 NT_STATUS_HAVE_NO_MEMORY(primary_address);
217 status = nbtd_add_socket(nbtsrv,
220 talloc_strdup(tmp_ctx, "255.255.255.255"),
221 talloc_strdup(tmp_ctx, "0.0.0.0"));
222 NT_STATUS_NOT_OK_RETURN(status);
225 for (i=0; i<num_interfaces; i++) {
226 const char *address = talloc_strdup(tmp_ctx, iface_n_ip(i));
227 const char *bcast = talloc_strdup(tmp_ctx, iface_n_bcast(i));
228 const char *netmask = talloc_strdup(tmp_ctx, iface_n_netmask(i));
230 status = nbtd_add_socket(nbtsrv, address, address, bcast, netmask);
231 NT_STATUS_NOT_OK_RETURN(status);
234 if (lp_wins_server_list()) {
235 status = nbtd_add_wins_socket(nbtsrv);
236 NT_STATUS_NOT_OK_RETURN(status);
239 talloc_free(tmp_ctx);
246 form a list of addresses that we should use in name query replies
247 we always place the IP in the given interface first
249 const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx)
251 struct nbtd_server *nbtsrv = iface->nbtsrv;
252 const char **ret = NULL;
253 struct nbtd_interface *iface2;
254 BOOL is_loopback = False;
256 if (iface->ip_address) {
257 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
258 ret = str_list_add(ret, iface->ip_address);
261 for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
262 if (iface2 == iface) continue;
264 if (!iface2->ip_address) continue;
267 if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
272 ret = str_list_add(ret, iface2->ip_address);
275 talloc_steal(mem_ctx, ret);
282 find the interface to use for sending a outgoing request
284 struct nbtd_interface *nbtd_find_interface(struct nbtd_server *nbtd_server,
287 struct nbtd_interface *iface;
288 /* try to find a exact match */
289 for (iface=nbtd_server->interfaces;iface;iface=iface->next) {
290 if (iface_same_net(address, iface->ip_address, iface->netmask)) {
295 /* no exact match, if we have the broadcast interface, use that */
296 if (nbtd_server->bcast_interface) {
297 return nbtd_server->bcast_interface;
300 /* fallback to first interface */
301 return nbtd_server->interfaces;