*/
#include "includes.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
#include "nbt_server/nbt_server.h"
#include "smbd/service_task.h"
#include "lib/socket/socket.h"
#include "system/network.h"
#include "lib/socket/netif.h"
#include "param/param.h"
+#include "lib/util/util_net.h"
/*
struct nbt_name_packet *packet,
struct socket_address *src)
{
- struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
+ struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
struct nbtd_interface);
struct nbtd_server *nbtsrv = iface->nbtsrv;
nbtsrv->stats.total_received++;
- /* see if its from one of our own interfaces - if so, then ignore it */
+ /* see if it's from one of our own interfaces - if so, then ignore it */
if (nbtd_self_packet_and_bcast(nbtsock, packet, src)) {
DEBUG(10,("Ignoring bcast self packet from %s:%d\n", src->addr, src->port));
return;
}
}
+static void nbtd_unexpected_handler(struct nbt_name_socket *nbtsock,
+ struct nbt_name_packet *packet,
+ struct socket_address *src)
+{
+ struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
+ struct nbtd_interface);
+ struct nbtd_server *nbtsrv = iface->nbtsrv;
+ struct nbtd_interface *i;
+ struct nbt_name_request *req = NULL;
+
+ nbtsrv->stats.total_received++;
+
+ DEBUG(10,("unexpected from src[%s] on interface[%p] %s/%s\n",
+ src->addr, iface, iface->ip_address, iface->netmask));
+
+ /* try the broadcast interface */
+ if (nbtsrv->bcast_interface) {
+ i = nbtsrv->bcast_interface;
+ req = idr_find(i->nbtsock->idr, packet->name_trn_id);
+ }
+
+ /* try the wins server client interface */
+ if (!req && nbtsrv->wins_interface && nbtsrv->wins_interface->nbtsock) {
+ i = nbtsrv->wins_interface;
+ req = idr_find(i->nbtsock->idr, packet->name_trn_id);
+ }
+
+ /* try all other interfaces... */
+ if (!req) {
+ for (i = nbtsrv->interfaces; i; i = i->next) {
+ if (i == iface) {
+ continue;
+ }
+ req = idr_find(i->nbtsock->idr, packet->name_trn_id);
+ if (req) break;
+ }
+ }
+
+ if (!req) {
+ DEBUG(10,("unexpected from src[%s] unable to redirected\n", src->addr));
+ return;
+ }
+
+ DEBUG(10,("unexpected from src[%s] redirected to interface[%p] %s/%s\n",
+ src->addr, i, i->ip_address, i->netmask));
+
+ /*
+ * redirect the incoming response to the socket
+ * we sent the matching request
+ */
+ nbt_name_socket_handle_response_packet(req, packet, src);
+}
/*
find a registered name on an interface
struct socket_address *bcast_address;
struct socket_address *unicast_address;
+ DEBUG(6,("nbtd_add_socket(%s, %s, %s, %s)\n", bind_address, address, bcast, netmask));
+
/*
we actually create two sockets. One listens on the broadcast address
for the interface, and the other listens on our specific address. This
iface->ip_address = talloc_steal(iface, address);
iface->netmask = talloc_steal(iface, netmask);
iface->names = NULL;
+ iface->wack_queue = NULL;
if (strcmp(netmask, "0.0.0.0") != 0) {
struct nbt_name_socket *bcast_nbtsock;
/* listen for broadcasts on port 137 */
- bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx, lp_iconv_convenience(nbtsrv->task->lp_ctx));
+ bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
if (!bcast_nbtsock) {
talloc_free(iface);
return NT_STATUS_NO_MEMORY;
}
bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name,
- bcast, lp_nbt_port(lp_ctx));
+ bcast, lpcfg_nbt_port(lp_ctx));
if (!bcast_address) {
talloc_free(iface);
return NT_STATUS_NO_MEMORY;
status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Failed to bind to %s:%d - %s\n",
- bcast, lp_nbt_port(lp_ctx), nt_errstr(status)));
+ bcast, lpcfg_nbt_port(lp_ctx), nt_errstr(status)));
talloc_free(iface);
return status;
}
}
/* listen for unicasts on port 137 */
- iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx,
- lp_iconv_convenience(nbtsrv->task->lp_ctx));
+ iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
if (!iface->nbtsock) {
talloc_free(iface);
return NT_STATUS_NO_MEMORY;
unicast_address = socket_address_from_strings(iface->nbtsock,
iface->nbtsock->sock->backend_name,
- bind_address, lp_nbt_port(lp_ctx));
+ bind_address, lpcfg_nbt_port(lp_ctx));
status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Failed to bind to %s:%d - %s\n",
- bind_address, lp_nbt_port(lp_ctx), nt_errstr(status)));
+ bind_address, lpcfg_nbt_port(lp_ctx), nt_errstr(status)));
talloc_free(iface);
return status;
}
talloc_free(unicast_address);
nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
+ nbt_set_unexpected_handler(iface->nbtsock, nbtd_unexpected_handler, iface);
/* also setup the datagram listeners */
status = nbtd_dgram_setup(iface, bind_address);
NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx,
struct interface *ifaces)
{
- int num_interfaces = iface_count(ifaces);
+ int num_interfaces = iface_list_count(ifaces);
int i;
TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
NTSTATUS status;
/* if we are allowing incoming packets from any address, then
we also need to bind to the wildcard address */
- if (!lp_bind_interfaces_only(lp_ctx)) {
+ if (!lpcfg_bind_interfaces_only(lp_ctx)) {
const char *primary_address;
+ primary_address = iface_list_first_v4(ifaces);
+
/* the primary address is the address we will return
for non-WINS queries not made on a specific
interface */
- if (num_interfaces > 0) {
- primary_address = iface_n_ip(ifaces, 0);
- } else {
+ if (primary_address == NULL) {
primary_address = inet_ntoa(interpret_addr2(
- lp_netbios_name(lp_ctx)));
+ lpcfg_netbios_name(lp_ctx)));
}
+
primary_address = talloc_strdup(tmp_ctx, primary_address);
NT_STATUS_HAVE_NO_MEMORY(primary_address);
}
for (i=0; i<num_interfaces; i++) {
- const char *bcast = iface_n_bcast(ifaces, i);
+ const char *bcast;
const char *address, *netmask;
+ if (!iface_list_n_is_v4(ifaces, i)) {
+ /* v4 only for NBT protocol */
+ continue;
+ }
+
+ bcast = iface_list_n_bcast(ifaces, i);
/* we can't assume every interface is broadcast capable */
if (bcast == NULL) continue;
- address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
+ address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
bcast = talloc_strdup(tmp_ctx, bcast);
- netmask = talloc_strdup(tmp_ctx, iface_n_netmask(ifaces, i));
+ netmask = talloc_strdup(tmp_ctx, iface_list_n_netmask(ifaces, i));
- status = nbtd_add_socket(nbtsrv, lp_ctx,
+ status = nbtd_add_socket(nbtsrv, lp_ctx,
address, address, bcast, netmask);
NT_STATUS_NOT_OK_RETURN(status);
}
- if (lp_wins_server_list(lp_ctx)) {
+ if (lpcfg_wins_server_list(lp_ctx)) {
status = nbtd_add_wins_socket(nbtsrv);
NT_STATUS_NOT_OK_RETURN(status);
}
bool is_loopback = false;
if (iface->ip_address) {
- is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
+ is_loopback = iface_list_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
ret = str_list_add(ret, iface->ip_address);
}
if (!iface2->ip_address) continue;
if (!is_loopback) {
- if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
+ if (iface_list_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
continue;
}
}
/* try to find a exact match */
for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
- if (iface_same_net(address, cur->ip_address, cur->netmask)) {
+ if (iface_list_same_net(address, cur->ip_address, cur->netmask)) {
+ DEBUG(10,("find interface for dst[%s] ip: %s/%s (iface[%p])\n",
+ address, cur->ip_address, cur->netmask, cur));
return cur;
}
}
/* no exact match, if we have the broadcast interface, use that */
if (allow_bcast_iface && nbtd_server->bcast_interface) {
- return nbtd_server->bcast_interface;
+ cur = nbtd_server->bcast_interface;
+ DEBUG(10,("find interface for dst[%s] ip: %s/%s (bcast iface[%p])\n",
+ address, cur->ip_address, cur->netmask, cur));
+ return cur;
}
/* fallback to first interface */
- return nbtd_server->interfaces;
+ cur = nbtd_server->interfaces;
+ DEBUG(10,("find interface for dst[%s] ip: %s/%s (default iface[%p])\n",
+ address, cur->ip_address, cur->netmask, cur));
+ return cur;
}
/*