summaryrefslogtreecommitdiff
path: root/source4/nbt_server/interfaces.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/nbt_server/interfaces.c')
-rw-r--r--source4/nbt_server/interfaces.c125
1 files changed, 68 insertions, 57 deletions
diff --git a/source4/nbt_server/interfaces.c b/source4/nbt_server/interfaces.c
index 303802e2cd4..8c5566c819e 100644
--- a/source4/nbt_server/interfaces.c
+++ b/source4/nbt_server/interfaces.c
@@ -25,6 +25,23 @@
#include "nbt_server/nbt_server.h"
#include "smbd/service_task.h"
+
+/*
+ receive an incoming request and dispatch it to the right place
+*/
+static void nbt_request_handler(struct nbt_name_socket *nbtsock,
+ struct nbt_name_packet *packet,
+ const char *src_address, int src_port)
+{
+ switch (packet->operation & NBT_OPCODE) {
+ case NBT_OPCODE_QUERY:
+ nbt_request_query(nbtsock, packet, src_address, src_port);
+ break;
+ }
+}
+
+
+
/*
find a registered name on an interface
*/
@@ -43,56 +60,24 @@ struct nbt_iface_name *nbt_find_iname(struct nbt_interface *iface, struct nbt_na
}
/*
- see if a src address matches an interface
-*/
-static BOOL nbt_iface_match(struct nbt_interface *iface, const char *src_address)
-{
- struct ipv4_addr ip1, ip2, mask;
- ip1 = interpret_addr2(iface->ip_address);
- ip2 = interpret_addr2(src_address);
- mask = interpret_addr2(iface->netmask);
- return same_net(ip1, ip2, mask);
-}
-
-
-/*
- find the appropriate interface for a incoming packet. If a local interface isn't
- found then the general broadcast interface is used
-*/
-struct nbt_interface *nbt_iface_find(struct nbt_name_socket *nbtsock, const char *src_address)
-{
- struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbt_interface);
- struct nbt_server *nbtsrv = iface->nbtsrv;
-
- /* it might have been received by one of our specific bound
- addresses */
- if (iface != nbtsrv->bcast_interface) {
- return iface;
- }
-
- /* it came in on our broadcast interface - try to find a match */
- for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
- if (nbt_iface_match(iface, src_address)) {
- return iface;
- }
- }
-
- /* it didn't match any specific interface - use our general broadcast interface */
- return nbtsrv->bcast_interface;
-}
-
-
-/*
start listening on the given address
*/
static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv,
- const char *bind_address,
const char *address,
const char *bcast,
const char *netmask)
{
struct nbt_interface *iface;
NTSTATUS status;
+ struct nbt_name_socket *bcast_nbtsock;
+
+ /*
+ we actually create two sockets. One listens on the broadcast address
+ for the interface, and the other listens on our specific address. This
+ allows us to run with "bind interfaces only" while still receiving
+ broadcast addresses, and also simplifies matching incoming requests
+ to interfaces
+ */
iface = talloc(nbtsrv, struct nbt_interface);
NT_STATUS_HAVE_NO_MEMORY(iface);
@@ -103,10 +88,25 @@ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv,
iface->netmask = talloc_steal(iface, netmask);
iface->names = NULL;
+ if (strcmp(netmask, "0.0.0.0") != 0) {
+ bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(iface->ip_address);
+
+ status = socket_listen(bcast_nbtsock->sock, bcast, lp_nbt_port(), 0, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("Failed to bind to %s:%d - %s\n",
+ bcast, lp_nbt_port(), nt_errstr(status)));
+ talloc_free(iface);
+ return status;
+ }
+
+ nbt_set_incoming_handler(bcast_nbtsock, nbt_request_handler, iface);
+ }
+
iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
NT_STATUS_HAVE_NO_MEMORY(iface->ip_address);
- status = socket_listen(iface->nbtsock->sock, bind_address, lp_nbt_port(), 0, 0);
+ status = socket_listen(iface->nbtsock->sock, address, lp_nbt_port(), 0, 0);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Failed to bind to %s:%d - %s\n",
address, lp_nbt_port(), nt_errstr(status)));
@@ -114,8 +114,11 @@ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv,
return status;
}
+ /* we need to be able to send broadcasts out */
socket_set_option(iface->nbtsock->sock, "SO_BROADCAST", "1");
+ nbt_set_incoming_handler(iface->nbtsock, nbt_request_handler, iface);
+
if (strcmp(netmask, "0.0.0.0") == 0) {
DLIST_ADD(nbtsrv->bcast_interface, iface);
} else {
@@ -135,29 +138,37 @@ NTSTATUS nbt_startup_interfaces(struct nbt_server *nbtsrv)
int i;
TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
NTSTATUS status;
- const char *primary_address;
- /* 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 = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_ip(0)));
- } else {
- primary_address = sys_inet_ntoa(interpret_addr2(lp_netbios_name()));
- }
+ /* if we are allowing incoming packets from any address, then
+ we also need to bind to the wildcard address */
+ if (!lp_bind_interfaces_only()) {
+ const char *primary_address;
+
+ /* 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 = sys_inet_ntoa(*iface_n_ip(0));
+ } else {
+ primary_address = sys_inet_ntoa(interpret_addr2(
+ lp_netbios_name()));
+ }
+ primary_address = talloc_strdup(tmp_ctx, primary_address);
+ NT_STATUS_HAVE_NO_MEMORY(primary_address);
- status = nbt_add_socket(nbtsrv,
- "0.0.0.0",
- primary_address,
- talloc_strdup(tmp_ctx, "255.255.255.255"),
- talloc_strdup(tmp_ctx, "0.0.0.0"));
- NT_STATUS_NOT_OK_RETURN(status);
+ status = nbt_add_socket(nbtsrv,
+ primary_address,
+ talloc_strdup(tmp_ctx, "255.255.255.255"),
+ talloc_strdup(tmp_ctx, "0.0.0.0"));
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
for (i=0; i<num_interfaces; i++) {
const char *address = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_ip(i)));
const char *bcast = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_bcast(i)));
const char *netmask = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_netmask(i)));
- status = nbt_add_socket(nbtsrv, address, address, bcast, netmask);
+ status = nbt_add_socket(nbtsrv, address, bcast, netmask);
NT_STATUS_NOT_OK_RETURN(status);
}