r5171: added support for "bind interfaces only" in nbtd. The solution was to
authorAndrew Tridgell <tridge@samba.org>
Wed, 2 Feb 2005 10:29:50 +0000 (10:29 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:09:28 +0000 (13:09 -0500)
bind twice on each interface, once using the broadcast address and
once using the specific IP. We then only listen on the wildcard
address if we don't have "bind interface only" set. This also happens
to simplify the code that finds the right interface for an incoming
request.

source/nbt_server/interfaces.c
source/nbt_server/nbt_server.c
source/nbt_server/nodestatus.c
source/nbt_server/query.c
source/nbt_server/register.c

index 303802e2cd4feeb7e84e72c0073e27f7df01a712..8c5566c819ef18eeddee15c5c662f2d364d092b3 100644 (file)
 #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
 */
@@ -42,57 +59,25 @@ struct nbt_iface_name *nbt_find_iname(struct nbt_interface *iface, struct nbt_na
        return NULL;
 }
 
-/*
-  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);
        }
 
index 6e4acba115651b9c6cab99513e7cfbccbbd008d6..4884398d78d264d25b5c42c05db0704cd958d30f 100644 (file)
 #include "nbt_server/nbt_server.h"
 
 
-/*
-  receive an incoming request
-*/
-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;
-       }
-}
-
-
 /*
   startup the nbtd task
 */
 static void nbtd_task_init(struct task_server *task)
 {
        struct nbt_server *nbtsrv;
-       struct nbt_interface *iface;
        NTSTATUS status;
 
        nbtsrv = talloc(task, struct nbt_server);
@@ -67,13 +51,6 @@ static void nbtd_task_init(struct task_server *task)
                return;
        }
 
-       /* setup the incoming request handler for all our interfaces */
-       for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
-               nbt_set_incoming_handler(iface->nbtsock, nbt_request_handler, iface);
-       }
-       nbt_set_incoming_handler(nbtsrv->bcast_interface->nbtsock, nbt_request_handler, 
-                                nbtsrv->bcast_interface);
-
        /* start the process of registering our names on all interfaces */
        nbt_register_names(nbtsrv);
 }
index f57c86d10f8ffa81cd5af28189cf6b84196fee88..36c37073741659af92783c27e91c324a6b93c222 100644 (file)
@@ -99,12 +99,10 @@ void nbt_query_status(struct nbt_name_socket *nbtsock,
                      struct nbt_name_packet *packet, 
                      const char *src_address, int src_port)
 {
-       struct nbt_interface *iface;
        struct nbt_name *name;
        struct nbt_iface_name *iname;
-
-       /* find the interface for this query */
-       iface = nbt_iface_find(nbtsock, src_address);
+       struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, 
+                                                     struct nbt_interface);
 
        NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
        NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_type == NBT_QTYPE_STATUS);
index 2d2e75d51eef207fded7c6918f554ec9f1fb6ab9..6dab18cfbe8eaed72c27d07ffa648c0229c487bd 100644 (file)
@@ -81,9 +81,10 @@ void nbt_request_query(struct nbt_name_socket *nbtsock,
                       struct nbt_name_packet *packet, 
                       const char *src_address, int src_port)
 {
-       struct nbt_interface *iface;
        struct nbt_iface_name *iname;
        struct nbt_name *name;
+       struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, 
+                                                     struct nbt_interface);
 
        /* see if its a node status query */
        if (packet->qdcount == 1 &&
@@ -99,9 +100,6 @@ void nbt_request_query(struct nbt_name_socket *nbtsock,
                return;
        }
 
-       /* find the interface for this query */
-       iface = nbt_iface_find(nbtsock, src_address);
-
        NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
        NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_type == NBT_QTYPE_NETBIOS);
        NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_class == NBT_QCLASS_IP);
index 4f954c189a878f906bf62c776f4acf2bbe59c513..6b75c992a99fdc3ce22fcb0375a5f89efd905948 100644 (file)
@@ -209,7 +209,10 @@ static void nbt_register_name(struct nbt_server *nbtsrv,
        }
 
        /* register on our general broadcast interface as a permanent name */
-       nbt_register_name_iface(nbtsrv->bcast_interface, name, type, nb_flags | NBT_NM_PERMANENT);
+       if (nbtsrv->bcast_interface) {
+               nbt_register_name_iface(nbtsrv->bcast_interface, name, type, 
+                                       nb_flags | NBT_NM_PERMANENT);
+       }
 
        /* TODO: register with our WINS servers */
 }